1

当我尝试即时计算 zip 文件的 MD5 并同时解压缩时,对于某些 zip 文件它不起作用:尽管文件没有损坏,但 MD5 总和不正确。

这是我的代码片段:

MessageDigest lMd = MessageDigest.getInstance("MD5");

FileOutputStream lFos = null;
try (DigestInputStream lDis = new DigestInputStream(lListener.getInputStream(), lMd);
                            ZipInputStream lZip = new ZipInputStream(lDis)) {

    // Read the response content
    //get the zipped file list entry
    ZipEntry lZipEntry = lZip.getNextEntry();

    while (lZipEntry != null) {
        String lFileName = lZipEntry.getName();

        File lNewFile = new File(UPDATE_FOLDER + File.separator + lFileName);

        if (lZipEntry.isDirectory()) {
            lNewFile.mkdirs();
        } else {
            //create all non exists folders
            new File(lNewFile.getParent()).mkdirs();

            lFos = new FileOutputStream(lNewFile);             

            int lRead;
            while ((lRead = lZip.read(lBuffer)) > -1) {
                lFos.write(lBuffer, 0, lRead);
            }

            lFos.close();   
        }

        lZipEntry = lZip.getNextEntry();
    }

    lZip.closeEntry();
} finally {
    if (lFos != null) {
        lFos.close();
}
                        byte[] lDigest = lMd.digest();

                    StringBuffer lHexString = new StringBuffer();
                    for (int lI = 0; lI < lDigest.length; lI++) {
                        if ((0xFF & lDigest[lI]) < 0x10) {
                            lHexString.append("0"
                                    + Integer.toHexString((0xFF & lDigest[lI])));
                        } else {
                            lHexString.append(Integer.toHexString(0xFF & lDigest[lI]));
                        }
                    }
                    String lDigestStr = lHexString.toString();

你能帮助我吗?

谢谢!前!

4

1 回答 1

0

您需要将这两个操作分开。ZipInputStream不是为了完全使用底层流而构建的。原因是 ZIP 文件格式基本上如下所示:

<file header><file data>
<file header><file data>
<file header><file data>
<...>
<last file header><last file data>
<directory header>
<directory header>
<directory header>
<...>
<last directory header>

<file header>并且<directory header>有不同的签名。下面是什么ZipInputStream时候getNextEntry()被调用:

if (get32(tmpbuf, 0) != LOCSIG) {
    return null;
}

它验证它刚刚读取的缓冲区是否以字符“PK\003\004”开头,这将是一个正确的文件头。但是,一旦目录头开始,这将开始返回null,因为目录头是“PK\001\002”。</p>

在此之后,您ZipInputStreamnull停止getNextEntry()使用它。针对您的特定问题的唯一解决方案是首先验证文件,然后将其解压缩。如评论中所述,无论如何您都应该这样做,因为如果验证失败,您绝对不应该使用该文件!

于 2016-03-09T07:16:39.147 回答