4

Possible Duplicate:
Appending files to a zip file with Java

Hello Java Developers,

Here's the scenario:

Say I have a textfile named sample.txt. What I actually want to do is to put the sample.txt file into a *.zip file named TextFiles.zip.

Here's what I have learned so far.

try{
    File f = new File(compProperty.getZIP_OUTPUT_PATH());
    zipOut = new ZipOutputStream(new FileOutputStream(f));
    ZipEntry zipEntry = new ZipEntry("sample.txt");
    zipOut.putNextEntry(zipEntry);
    zipOut.closeEntry();
    zipOut.close();
    System.out.println("Done");

} catch ( Exception e ){
    // My catch block
}

My code so far creates a *.zip file and insert the sample.txt file.
My question is how would I be able to insert an existing file to the created *.zip file?
If your answer has anything to do with TrueZIP, please post an SSCCE.

I have done the following:

  • Googled
  • Search for existing question. ( Found few. No answer. Some didn't answer my particular question.
  • Read TrueZip. Yet, I couldn't understand a thing. ( Please do understand )
Community
  • 1
  • 1
Michael 'Maik' Ardan
  • 4,213
  • 9
  • 37
  • 60
  • A rare question that doesn't need editing! – syb0rg Jan 16 '13 at 02:51
  • By append, do you mean inserting another file into the zip? What would your zip look like when it's working the way you want? – Daniel Kaplan Jan 16 '13 at 02:51
  • 1
    1- You example scares me, as you are not actually coping any data to the zip file, just preparing an index. 2- Zip doesn't have a concept of "append". Append is normally achieved by copying the contents of the existing Zip file to a new Zip file, adding in the new content, deleting the old Zip file and renaming the new one back into its place. You can take a look at [this](http://stackoverflow.com/questions/12164889/java-library-to-manipulate-jar-files/12167217#12167217) and [this](http://stackoverflow.com/questions/12064676/appending-zip-archive-debugging/12065042#12065042) for some examples – MadProgrammer Jan 16 '13 at 03:04
  • @Daniel Kaplan Yes, sort of. The *.zip would contain the sample.txt file. However, I want the sample.txt file created through a text editor rather than creating the file by constructing a ZipEntry. As how I learned it, please correct me if I'm wrong, you create and populate the entries through ZipEntry before inserting into a ZipOutputStream. – Michael 'Maik' Ardan Jan 16 '13 at 03:04
  • @MadProgrammer Thanks MadProgrammer. As usual, professional reply. I have edited the question and changed the append to insert. – Michael 'Maik' Ardan Jan 16 '13 at 03:05

3 Answers3

8

Using the inbuilt Java API. This will add a file to a Zip File, this will replace any existing Zip files that may exist, creating a new Zip file.

public class TestZip02 {

  public static void main(String[] args) {
    try {
      zip(new File("TextFiles.zip"), new File("sample.txt"));
    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }

  public static void zip(File zip, File file) throws IOException {
    ZipOutputStream zos = null;
    try {
      String name = file.getName();
      zos = new ZipOutputStream(new FileOutputStream(zip));

      ZipEntry entry = new ZipEntry(name);
      zos.putNextEntry(entry);

      FileInputStream fis = null;
      try {
        fis = new FileInputStream(file);
        byte[] byteBuffer = new byte[1024];
        int bytesRead = -1;
        while ((bytesRead = fis.read(byteBuffer)) != -1) {
          zos.write(byteBuffer, 0, bytesRead);
        }
        zos.flush();
      } finally {
        try {
          fis.close();
        } catch (Exception e) {
        }
      }
      zos.closeEntry();

      zos.flush();
    } finally {
      try {
        zos.close();
      } catch (Exception e) {
      }
    }
  }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Great! As expected from you. Thank you! This is what exactly I was looking for. – Michael 'Maik' Ardan Jan 16 '13 at 03:31
  • This actually answered my question. However, for my learning, what do the try block under FileInputStream fis = null; does? – Michael 'Maik' Ardan Jan 16 '13 at 03:38
  • Basic a Zip is split into 2 sections, entries and data. Entries describe the data blocks, including where to find them, so, once your added an entry, it opens a block for you to write to. The secion you are talking about basically uses a `FileInputStream` to read the file contents and pass it through the `ZipOutputStream` which will compress the file contents and add it to the data block of the current entry. Once done, I `flush` the `ZipOutputStream` (because I'm paranoid) and close of the entry. – MadProgrammer Jan 16 '13 at 03:44
3

Here you can get answer for your question: http://truezip.schlichtherle.de/2011/07/26/appending-to-zip-files/

Kanagaraj M
  • 956
  • 8
  • 18
1

It seems that, according to the epic JDK reference, you could use a while zis.getNextEntry() != null loop to loop through the file (where zis is a ZipInputStream), then use zis.read() to read into an array, which is sent to an ArrayList or similar.

Then, one could use toArray(), "cast" it to a byte array with this method and zos.write() it into the output ZIP file (where zos is a ZipOutputStream), using zos.putNextEntry() to make new entries. (You will need to save the ZipEntry and get its name with ze.getName(), with ze being a ZipEntry.)You should replace T with Byte and byte (use byte everywhere but the for loop body) and may need to modify the casting code to use Byte.byteValue() to convert from Byte (wrapper class) to byte (primitive type), like so:

for(int i = 0; i < objects.length; i++) {
    convertedObjects[i] = (Byte)objects[i].byteValue();
}

Note that this is untested and based on the JDK (entries ZipInputStream, ZipOutputStream, ArrayList, and Byte) and a Google search on array casting.

Sorry if that was a bit dense, and hope this helps!!

ameed
  • 1,132
  • 6
  • 25
  • Hi MathSquared, thanks for answering. Anyway, what do you mean by replacing T with Byte? I can't seem to understand what T means – Michael 'Maik' Ardan Jan 16 '13 at 03:16
  • In the method for array casting I linked to, it has `T` in the code. You will need to type `byte` in place of `T` (except in the `for` loop, where you should use the fragment I provided in my answer). – ameed Jan 16 '13 at 14:19