如何计算数据的CRC以通过zip条目的CRC验证它?

时间:2016-10-07 16:56:57

标签: java zip checksum crc

在我们开始之前:我是JAVA的绝对初学者。我一直是C ++编码器。所以当我在这里做蠢事时请告诉我!

我正在查询庞大的数据库并将该数据直接导出到zip文件中。我们在这里讨论的是35GB的数据,因此结果通过StringBuilder流式传输,当StringBuilder具有特定大小时,其数据将被发送到ZipOutputStream对象进行压缩。我重置StringBuilder并重复,直到所有数据都被处理和压缩。 这很好用。 zip文件总是很好,但是客户希望我进行额外的检查。

所以我希望能够从内存数据中自己计算校验和值,这样最后,我可以重新打开zip文件来检查它是否没有损坏,校验和是我期望的那样。

因此每次我将数据发送到ZipOuputStream时,我也会更新内部校验和。我使用CRC32类,它也在同一个zip库中,所以我希望zip条目使用相同的计算。

但是唉...计算出的校验和和zip条目的校验和不一样,而zip文件肯定没问题。

任何人都可以帮我解决这个问题吗?

这是一些代码。 这就是我创建zip文件,CRC类和StringBuilder的方法。

File zipFile = new File(outputZipFileName);
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
ZipEntry zipEntry = new ZipEntry(tableName + ".csv");
zipOut.putNextEntry(zipEntry);
CRC32 zipEntryCrc = new CRC32();
StringBuilder sbZipData = new StringBuilder();
sbZipData.ensureCapacity(memoryBufferSize);

这是我每次StringBuilder达到限制时或数据末尾时所做的事情:

byte[] sZipData = sbZipData.toString().getBytes();
zipEntryCrc.update(sZipData);
zipOut.write(sZipData, 0, sZipData.length);
zipOut.flush();
sbZipData.setLength(0);

以下是我重新打开生成的zip文件并测试校验和的方法:

ZipFile testZipFile = new ZipFile(outputZipFileName);
ZipEntry testZipEntry = testZipFile.getEntry(tableName + ".csv");
System.out.format("Calculated CRC: %8X, Zip entry CRC: %8X\n", zipEntryCrc.getValue(), testZipEntry.getCrc());
testZipFile.close();

你可以猜到,输出结果不一样:

Calculated CRC: 2E9F53AC, Zip entry CRC: 5270784D

顺便说一下。我知道我必须放置一些try-catch以防止代码在找不到zip条目时停止。这只是我的第一次测试。

任何?

1 个答案:

答案 0 :(得分:2)

我复制了你的例子它确实有效,校验和是相同的,但是,我需要至少添加zipOut.close()调用:

    zipOut.write(sZipData, 0, sZipData.length);
    //zipOut.closeEntry();     // <===== optional
    zipOut.flush();
    zipOut.close();            // <=====
    sbZipData.setLength(0);

这里是完整的测试类:

import java.io.*;
import java.nio.charset.Charset;
import java.util.zip.*;

public class CRC32Test {

    public static void main(String[] args) throws IOException {
        // create test daata
        String input = "Hell is empty and all the devils are here. William Shakespeare";
        for (int i = 0; i < 15; i++) {
            input = input + "|" + input;
        }
        System.out.println("input length: " + input.length());

        // get bytes from string
        byte bytes[] = input.getBytes();

        // compute checksum
        Checksum checksum = new CRC32();
        checksum.update(bytes, 0, bytes.length);

        // get current checksum value
        long checksumValue = checksum.getValue();

        System.out.format("CRC32 checksum for input string: %8X\n", checksumValue);
        System.out.println("------------------");

        String outputZipFileName = "t.zip";
        int memoryBufferSize = 1024;
        String tableName = "string";
        Charset charset = Charset.forName("UTF-8");

        File zipFile = new File(outputZipFileName);
        if (zipFile.exists()) zipFile.delete();

        ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile), charset);
        ZipEntry zipEntry = new ZipEntry(tableName + ".csv");
        zipOut.putNextEntry(zipEntry);
        CRC32 zipEntryCrc = new CRC32();
        StringBuilder sbZipData = new StringBuilder();
        sbZipData.ensureCapacity(memoryBufferSize);

        sbZipData.append(input);   // <=====

        byte[] sZipData = sbZipData.toString().getBytes("UTF-8");
        zipEntryCrc.update(sZipData);
        zipOut.write(sZipData, 0, sZipData.length);
        //zipOut.closeEntry();     // <===== optional
        zipOut.flush();
        zipOut.close();            // <=====
        sbZipData.setLength(0);

        ZipFile testZipFile = new ZipFile(outputZipFileName, charset);
        ZipEntry testZipEntry = testZipFile.getEntry(tableName + ".csv");
        System.out.format("Calculated CRC: %8X, Zip entry CRC: %8X\n", zipEntryCrc.getValue(), testZipEntry.getCrc());
        testZipFile.close();
    }
}