如果没有发生异常,ZipEntry.getCrc()是否可能不正确?

时间:2017-12-05 00:28:34

标签: java zip

我在java.util.zip包中使用Java的ZIP存档API。我在Apache NetBeans' source repository中查看的一些代码使用以下例程计算正在读取的ZIP存档中每个条目的CRC32:

private long computeCRC32(InputStream is) throws IOException {
    byte[] buf = new byte[4096];
    CRC32 crc32 = new CRC32();
    int read;
    while ((read = is.read(buf)) != -1) {
        crc32.update(buf, 0, read);
    }
    return crc32.getValue();
}

每个ZIP条目都会调用一次此例程:

File f = new File("a.zip");
try (ZipFile zipFile = new ZipFile(f)) {
    Enumeration<? extends ZipEntry> entries = zipFile.entries();
    while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();
        long crc;
        try (InputStream is = zipFile.getInputStream(entry)) {
            crc = computeCRC32(is);
        }
        // do something with `crc'
    }
}

我想知道简单地调用ZipEntry.getCrc()(如果它返回-1以外的东西)而不是调用computeCRC32()会更好。

我担心的一个问题是,如果ZIP存档格式错误,getCrc()可能会返回不正确的值。

对于某些ZIP条目,ZipEntry.getCrc()是否可以返回除-1以外的值,而不是computeCRC32()计算的值,并且可以完全读取格式错误的ZIP存档而不会发生任何异常?

UPDATE 我使用十六进制编辑器来更改存储在测试ZIP存档的本地文件头中的CRC32。运行我的测试程序,我没有观察到异常,但是getCrc()返回了正确的CRC32而不是更改的值。

供参考,这是我的测试程序:

import java.io.*;
import java.util.*;
import java.util.zip.*;

public class ZipCrcTest {

    public static void main(String[] args) throws IOException {
        File f = new File("a.zip");
        try (ZipFile zipFile = new ZipFile(f)) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                long crc;
                try (InputStream is = zipFile.getInputStream(entry)) {
                    crc = computeCRC32(is);
                }
                System.out.printf("%s %x (computed %x)\n", entry.getName(), entry.getCrc(), crc);
                if (entry.getCrc() != -1L && entry.getCrc() != crc) {
                    System.err.printf("Crc different for %s!\n", entry.getName());
                }
            }
        }
    }

    private static long computeCRC32(InputStream is) throws IOException {
        byte[] buf = new byte[4096];
        CRC32 crc32 = new CRC32();
        int read;
        while ((read = is.read(buf)) != -1) {
            crc32.update(buf, 0, read);
        }
        return crc32.getValue();
    }
}

1 个答案:

答案 0 :(得分:0)

事实证明答案是“是”。

当我同样在ZIP存档的中央目录部分更改了zip条目CRC32的副本时,getCrc()返回了更改的值,并且没有抛出任何异常。