ZipInputStream.getNextEntry returns null in some zip files

I have a simple code for extracting zip files, it worked fine as expected, but during the test I tried my code with some zip files (fonts, icons and templates downloaded from the Internet) to make sure that it should extract any zip files, but not working with some zip files, here is the summary code to regenerate this problem:

package com.test.mytest; import java.io.FileInputStream; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; public class ZipExtractTest { public static final String ZIP_FILE = "/Users/XXXXX/Downloads/janne.zip"; public static void main(String[]args) { unzipFile(ZIP_FILE); unzipStream(ZIP_FILE); } public static void unzipFile(String zipName) { try { ZipFile zf = new ZipFile(zipName); Enumeration ent = zf.entries(); while(ent.hasMoreElements()) { System.out.println(ent.nextElement()); } } catch(Exception e) { System.out.println(e); } } public static void unzipStream(String zipName) { try { ZipInputStream zis = new ZipInputStream(new FileInputStream(zipName)); ZipEntry ze = zis.getNextEntry(); if(ze == null) { System.out.println("unable to get first entry from zip file"); zis.close(); return; } while(ze != null) { System.out.println("Entry Found: " + ze); ze = zis.getNextEntry(); } zis.closeEntry(); zis.close(); } catch(Exception e) { System.out.println(e); } } } 

In fact, in my real application, I have to extract zip files through input streams. In the above code, I am trying to extract "janne.zip". I downloaded this file from http://www.iconian.com/fonts/janne.zip I can extract it using any zip -tool file and surprisingly using the "unzipFile (String zipName)" method, but using the unzipStream ( String zipName)

 ZipEntry ze = zis.getNextEntry(); 

returns null

any help would be appreciated

+8
java unzip decompression zipfile
source share
3 answers

Not an answer to the question why this particular file does not work with java.util.zip , but if you have the opportunity to replace using java.util.zip.ZipInputStream Apache commons-compress org.apache.commons.compress.archivers.zip.ZipArchiveInputStream (which should be compatible with the API), then I just checked this in your example file and it seems to work successfully.

I usually find commons-compress more reliable than java.util.zip when unpacking files created by tools other than the java.util.zip classes themselves.

Edit: I debugged work a bit in Eclipse, and it looks like this particular zip file has a single segment marker 0x30304b50 in front of the LOC signature ( 0x04034b50 ) of the first local record header. This is something that commons-compress knows how to handle , but java.util.zip does not - if juzZipInputStream sees anything other than a LOC signature then getNextEntry() will return null .

+13
source share

Funny!

I debugged your code and got the same error. I found a header check in the ZipInputStream implementation, but not in the ZipFile implementation.

Do not ask me why, but the title in your zip file is invalid !

 Your file is starting with: 50 4B 30 30 50 4B 03 04 A valid Zip File Header is: 50 4B 03 04 

If you delete the first bytes ( 50 4B 30 30 ) from your file, you have the correct header, you can read the file!

+4
source share


I had the same problem! Luckily for me, I was able to solve it.
I first reset the blob data in the database, and then used java code to zip it using ZipInputStream. Although I'm not sure, ZipEntry's null issue could be due to two things:
1. Blob data in the database is not saved correctly (or may already be compressed, some databases compress blob data during storage, you can do this too).
2. I / O streams can also cause problems, see this


Here is a detailed description of what I did:
1. reset the blob field in the database using EMPTY_BLOB and commit the changes
2. used the java program below to update the blob field with the .xls file

 DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver ()); // register driver Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@my-local-database:1521:test", "test1", "test1"); // It faster when auto commit is off: conn.setAutoCommit (false); try { PreparedStatement pstmt = conn.prepareStatement("update content set file_content = ? where CONTENT_ID=2006"); File blob = new File("C:/Users/ankur/Desktop/Book1.xls"); FileInputStream in = new FileInputStream(blob); pstmt.setBinaryStream(1, in); pstmt.executeUpdate(); conn.commit(); conn.close(); System.out.println("file updated"); } catch (SQLException e) { e.printStackTrace(); } 

Please note that the above code will work, but it absolutely does not demonstrate coding standards and methods.
3. The zip method used below for data compression

 public byte[] zipByteArray(String primaryKey, byte[] input) throws IOException{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos); ZipEntry entry = new ZipEntry(primaryKey); entry.setSize(input.length); zos.putNextEntry(entry); zos.write(input); zos.closeEntry(); zos.close(); return baos.toByteArray(); } 

The above method takes a byte array, encrypts it, puts it in a ByteArrayOutputStream. You can use ByteArrayOutputStream itself, due to some requirements I convert it to an array of bytes.
4. Then I insert the above byte array into the blob field using the prepared statement
5. If I use the unzip code below, it works great!

 public byte[] unzipInputStream(InputStream is) throws IOException { ByteArrayOutputStream byteArrayOutputStream = null; ZipInputStream zipIs = new ZipInputStream(new BufferedInputStream(is)); byteArrayOutputStream = new ByteArrayOutputStream(); ZipEntry entry = zipIs.getNextEntry(); while (entry != null) { byte[] tmp = new byte[2048]; BufferedOutputStream bos = null; bos = new BufferedOutputStream(byteArrayOutputStream); int size = 0; while ((size = zipIs.read(tmp)) != -1) { bos.write(tmp, 0, size); } bos.flush(); bos.close(); entry = zipIs.getNextEntry(); } zipIs.close(); return byteArrayOutputStream.toByteArray(); 

The output of the above method is the unpacked data.

0
source share

All Articles