在我们开始之前:我是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条目时停止。这只是我的第一次测试。
任何?
答案 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();
}
}