如何计算数据的 CRC 以使用 zip 条目的 CRC 对其进行验证?
How to calculate the CRC of data to verify it with the CRC of a zip entry?
开始之前:我是 JAVA 的绝对初学者。我一直是一名 C++ 程序员。所以当我在这里做傻事时请告诉我!
我正在查询一个巨大的数据库并将该数据直接导出到一个 zip 文件中。我们在这里讨论的是 35GB 的数据,因此结果通过 StringBuilder 流式传输,当 StringBuilder 具有特定大小时,其数据将发送到 ZipOutputStream 对象进行压缩。我重置 StringBuilder 并重复,直到所有数据都已处理和压缩。
这很好用。 zip 文件总是好的,但客户希望我进行额外检查。
所以我希望能够自己根据内存数据中的校验和值计算校验和值,以便最后我可以重新打开 zip 文件以检查它是否未损坏以及校验和是否符合我的预期成为.
所以每次我向 ZipOuputStream 发送数据时,我也会更新我的内部校验和。我为此使用 CRC32 class,它也在同一个 zip 库中,所以我希望 zip 条目使用相同的计算。
但是,唉...计算出的校验和与 zip 条目的校验和不一样,而 zip 文件肯定没问题。
谁能帮我解决这个问题?
这是一些代码。
这就是我创建 zip 文件、CRC class 和 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 条目时停止。这只是我的第一次测试。
有人吗?
我复制了你的例子,它确实有效,校验和是相同的,但是,我至少需要添加 zipOut.close()
调用:
zipOut.write(sZipData, 0, sZipData.length);
//zipOut.closeEntry(); // <===== optional
zipOut.flush();
zipOut.close(); // <=====
sbZipData.setLength(0);
这里是完整的测试class:
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();
}
}
开始之前:我是 JAVA 的绝对初学者。我一直是一名 C++ 程序员。所以当我在这里做傻事时请告诉我!
我正在查询一个巨大的数据库并将该数据直接导出到一个 zip 文件中。我们在这里讨论的是 35GB 的数据,因此结果通过 StringBuilder 流式传输,当 StringBuilder 具有特定大小时,其数据将发送到 ZipOutputStream 对象进行压缩。我重置 StringBuilder 并重复,直到所有数据都已处理和压缩。 这很好用。 zip 文件总是好的,但客户希望我进行额外检查。
所以我希望能够自己根据内存数据中的校验和值计算校验和值,以便最后我可以重新打开 zip 文件以检查它是否未损坏以及校验和是否符合我的预期成为.
所以每次我向 ZipOuputStream 发送数据时,我也会更新我的内部校验和。我为此使用 CRC32 class,它也在同一个 zip 库中,所以我希望 zip 条目使用相同的计算。
但是,唉...计算出的校验和与 zip 条目的校验和不一样,而 zip 文件肯定没问题。
谁能帮我解决这个问题?
这是一些代码。 这就是我创建 zip 文件、CRC class 和 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 条目时停止。这只是我的第一次测试。
有人吗?
我复制了你的例子,它确实有效,校验和是相同的,但是,我至少需要添加 zipOut.close()
调用:
zipOut.write(sZipData, 0, sZipData.length);
//zipOut.closeEntry(); // <===== optional
zipOut.flush();
zipOut.close(); // <=====
sbZipData.setLength(0);
这里是完整的测试class:
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();
}
}