ZipInputStream.getNextEntry一些zip文件返回null(ZipInputS

2019-08-17 19:04发布

我有一个简单的代码来解压缩zip文件,它工作得很好的预期,但我的测试过程中我尽了一些zip文件(字体,图标和模板,我从互联网下载)的代码只是为了确保它应该提取任何zip文件提供的,但它不是用一些zip文件的工作,这里是最小化的代码再生此问题:

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);
        }
    }
}

其实在我的实际应用中,我有过inputstreams提取zip文件。 在上面的代码中,我试图提取“janne.zip”我从网上下载该文件http://www.iconian.com/fonts/janne.zip我可以使用任何ZIP工具来提取它令人惊讶的通过“unzipFile (字符串zipName)”的方法为好,但与unzipStream(字符串zipName)方法

ZipEntry ze = zis.getNextEntry();

返回null

任何帮助,将不胜感激

Answer 1:

不是一个答案,为什么这个特定的文件不一起工作java.util.zip ,但如果你可以选择更换你的使用java.util.zip.ZipInputStream与Apache的公地压缩 org.apache.commons.compress.archivers.zip.ZipArchiveInputStream (这应该是API兼容的),那么我刚刚测试了您的示例文件,它似乎能够成功。

一般来说,我发现公地压缩要远比更可靠java.util.zip在拆包比其他工具创建的文件java.util.zip类本身。

编辑:我做了一些调试Eclipse中,它看起来像这个特殊的zip文件中有一个单一的区段跨过标记0x30304b50的LOC签名(前0x04034b50第一入口的地方标头的)。 这是一件公地压缩知道如何处理 ,但java.util.zip没有-如果juzZipInputStream看到以外的任何其他一个LOC签名,然后getNextEntry()将返回null



Answer 2:

滑稽!

我调试你的代码,并得到了同样的错误。 我发现在ZipInputStream实施的头检查,但不是在zip文件执行。

不要问我为什么,但在你的zip文件的标题是无效的

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

如果删除第一个字节( 50 4B 30 30从文件)你有一个有效的头一个你可以阅读你的文件!



Answer 3:


我有同样的问题! 幸运的是我,我是能够解决这个问题。
第一I RESET在数据库中的二进制大对象数据然后用于Java代码使用ZipInputStream来压缩它。 虽然我不知道,空ZipEntry的问题可能是因为两件事情:
1.在数据库中的BLOB数据没有被正确存储(或可在其已经被压缩,一些数据库压缩在存储时BLOB数据,你可以过google一下)。
2.输入/输出流也可引起麻烦,看到此


下面是我所做的详细介绍:
1.使用EMPTY_BLOB重置blob字段在数据库和提交更改
2.用下面的java程序与.xls文件来更新blob字段

DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver ()); // register driver

Connection conn =
   DriverManager.getConnection ("jdbc:oracle:thin:@my-local-database:1521:test", "test1", "test1");

// It's 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();
}

请注意,上面的代码将工作,但它绝对不能证明编码标准和惯例。
3.用于下面的拉链方法来压缩数据

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();
}

上述方法需要一个字节数组,它拉链,将其放入一个ByteArrayOutputStream。 您可以选择使用ByteArrayOutputStream本身,由于一些要求,我将其转换为字节数组。
4.我然后使用准备语句插入blob字段上述字节数组
5.如果我用下面给出的解压缩代码,它工作正常!

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();

上述方法的输出是将解压缩后的数据。



文章来源: ZipInputStream.getNextEntry returns null on some zip files