Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read directly a file within a Zip file - Java

Tags:

java

zip

My situation is that I have a zip file that contains some files (txt, png, ...) and I want to read it directly by their names, I have tested the following code but no result (NullPointerExcepion):

InputStream in = Main.class.getResourceAsStream("/resouces/zipfile/test.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));

resources is a package and zipfile is a zip file.

like image 333
Adil Avatar asked Nov 15 '12 14:11

Adil


People also ask

How can I read the content of a Zip file without unzipping it in Java?

Methods. getComment(): String – returns the zip file comment, or null if none. getEntry(String name): ZipEntry – returns the zip file entry for the specified name, or null if not found. getInputStream(ZipEntry entry) : InputStream – Returns an input stream for reading the contents of the specified zip file entry.

Can Java read ZIP files?

Java API provides extensive support to read Zip files, all classes related to zip file processing are located in the java. util. zip package. One of the most common tasks related to zip archive is to read a Zip file and display what entries it contains, and then extract them in a folder.

Can you put a zip file inside a zip file?

Zipping zips is fine. If there is a problem, that would be a bug in the compression software :). You will probably not get any further compression for those files though unless you're using a higher level of compression. Zipping a zip can gain you more space even if the compression is the same.

How do I read a ZipInputStream file?

ZipInputStream. read(byte[] buf, int off, int len) method reads from the current ZIP entry into an array of bytes. If len is not zero, the method blocks until some input is available; otherwise, no bytes are read and 0 is returned.


2 Answers

If you can be sure that your zip file will never be packed inside another jar, you can use something like:

URL zipUrl = Main.class.getResource("/resources/zipfile.zip");
URL entryUrl = new URL("jar:" + zipUrl + "!/test.txt");
InputStream is = entryUrl.openStream();

Or:

URL zipUrl = Main.class.getResource("/resources/zipfile.zip");
File zipFile = new File(zipUrl.toURI());
ZipFile zip = new ZipFile(zipFile);
InputStream is = zip.getInputStream(zip.getEntry("test.txt"));

Otherwise, your choices are:

  • Use a ZipInputStream to scan through the zip file once for each entry that you need to load. This may be slow if you have a lot of resources, unless you can reuse the same ZipInputStream for all your resources.
  • Don't pack the resources in a nested zip file, and just inline them in the jar with the code.
  • Copy the nested zip file into a temporary directory, and access it using the ZipFile class.
like image 73
Martin Ellis Avatar answered Oct 17 '22 04:10

Martin Ellis


Your current approach is definitely not going to work. You made up an arbitrary 'access' scheme and used it in a class that has no idea what you are trying to do. What you can do is use a ZipInputStream to read the entry you are looking for:

URL zipFileURL = Thread.currentThread().getContextClassLoader().getResource("zipfile.zip");
InputStream inputStream = zipFileURL.openStream();
ZipInputStream zipInputStream = new ZipInputStream(inputStream);

ZipEntry zipEntry = null;

do {
    zipEntry = zipInputStream.getNextEntry();
    if(zipEntry == null) break;
}
while(zipEntry != null && (! "textfile".equals(zipEntry.getName()));

if(zipEntry != null ) {
    // do some stuff
}

This is adhoc code, fix it up to do what you need. Also, there might be some more efficient classes to handle Zip files, for example in the Apache Commons IO library.

like image 30
Perception Avatar answered Oct 17 '22 04:10

Perception