Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading a zip file within a jar file

Tags:

java

jar

zip

Previously we had some zip files within our web application. We would want to pares a specific text document within the zip file. This wasn't a problem:

URL url = getClass().getResource(zipfile);
ZipFile zip = new ZipFile(url.getFile().replaceAll("%20", " "));     
Entry entry = zip.getEntry("file.txt");

InputStream is = zip.getInputStream(entry);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

String line = reader.readLine();
while (line != null) {
    // do stuff
}

However we've moved these zip files into another module and want to package them within a jar. Unfortunately, creating the ZipFile now fails. I can get an InputStream for the zip: but I have no way of getting an input stream for the entry itself.

InputStream is = getClass().getResourceAsStream(zipfile);
ZipInputStream zis = new ZipInputStream(is);

ZipEntry entry = zis.getNextEntry();
while (entry != null && !entry.getName().equals("file.txt")) {
    entry = zis.getNextEntry();
}

but I have no way of getting an input stream for the entry itself. I tried finding the length of the entry and getting the next n bytes from the ZipInputStream but this didn't work for me. It seemed all bytes read were 0.

Is there a way round this or am I going to have to move the zip files back into the core project?

like image 712
samblake Avatar asked Sep 14 '10 15:09

samblake


2 Answers

How about TrueZip? Using it you could simply open the zipped file as if it was located inside a directory.

new FileOutputStream("/path/to/some-jar.jar/internal/zip/file.zip/myfile.txt");

According to the docs, infinite nesting is also supported. I have yet to actually use this project, but it's been on my radar for a while and it seems applicable to your problem.

Project Site: http://truezip.java.net/ (edited)

like image 128
Andy Avatar answered Sep 23 '22 14:09

Andy


entry can give you the inputstream of the inner-zip file.

InputStream innerzipstream = zip.getInputStream(entry);

So you can use

new ZipInputStream(innerzipstream);

and ask the ZipInputStream to retrieve the content of the inner-zip-file (in an ordered fashion, you don't have random access because it's a ZipInputStream)

Look at http://download.oracle.com/javase/1.4.2/docs/api/java/util/zip/ZipInputStream.html

Sequential zip access

As ZipInputStream is reading a zip file from an input stream it has to do things in order:

// DO THIS for each entry
ZipEntry e = zipInputStreamObj.getNextEntry();
e.getName // and all data
int size = e.getSize(); // the byte count
while (size > 0) {
   size -= zipInputStreamObj.read(...);
}
zipInputStreamObj.closeEntry();
// DO THIS END

zipInputStreamObj.close();

Note: I don't know if ZipInputStream.getNextEntry() returns null when end of zip file is reached or not. I hope so because I don't know other way to realize when there are no more entries.

like image 33
helios Avatar answered Sep 21 '22 14:09

helios