所以我会先说我的多线程程序无法输出 gzip 可以成功解压缩的东西,所以可能还有其他问题。但是我注意到的是,单线程和多线程的每个块的压缩大小是完全不同的。
在我的单线程运行中,我有一个设置了 SYNC_FLUSH 的 GZIPOutputStream(System.out, true)。我不断地从 system.in 读取,直到我的缓冲区已满。
GZIPOutputStream compressor = new GZIPOutputStream(System.out, true);
bytesRead = inBytes.read(buff,0,BLOCK_SIZE);
....
while(bytesRead != -1)
{
offset += bytesRead;
if (offset == BLOCK_SIZE)
{
compressor.write(buff,0,offset);
compressor.flush();
offset = 0;
}
if((bytesRead=inBytes.read(buff,offset,BLOCK_SIZE-offset)) == -1) {
compressor.write(buff,0,offset);
compressor.finish();
}
}
compressor.close();
如您所见,在缓冲区满了之后,我告诉压缩器写入输出,然后调用flush。确保我强制它压缩并清除任何剩余的输出,因此当它再次写入时,缓冲区中没有任何剩余数据。
因此,它与您的原始输入开始时的长度非常相似(因此每个块都是它自己的单独流)。
所以在我的多线程程序中,我没有一个 GZIPOutputStream 写入和刷新,而是有一堆线程,每个线程都有自己的 GZIPOutputStream。所以基本上,用对线程的调用替换该部分
List<Future<byte[]>> results = new ArrayList<Future<byte[]>>();
bytesRead = inBytes.read(buff,0,BLOCK_SIZE);
while(bytesRead != -1)
{
offset += bytesRead;
if (offset == BLOCK_SIZE)
{
results.add(exec.submit(new workerThread(buff,offset)));
offset = 0;
}
if((bytesRead=inBytes.read(buff,offset,BLOCK_SIZE-offset)) == -1) {
results.add(exec.submit(new workerThread(buff,offset)));
}
}
我只是将缓冲区传递给他们进行压缩。我所有的线程都是
private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
private byte[] finalOut;
....
public byte[] call() {
try{
GZIPOutputStream compress = new GZIPOutputStream (bOut, true);
compress.write(input,0,size);
compress.flush();
compress.close();
}
catch (IOException e)
{
e.printStackTrace();
System.exit(-1);
}
finalOut = bOut.toByteArray();
return finalOut;
}
我认为我所做的只是将压缩工作交给线程。我没有改变其他任何东西。但是,当我运行我的多线程程序并 hexdump 结果时,我注意到两个程序之间的每个块通常有很大不同。我使用了一个小缓冲区和小输入,因此更容易阅读。
我的多线程程序出现 crc 错误,这意味着至少 gzip 可以识别格式并开始解压缩。只是当它完成时,最终的结果与它期望的 CRC 不匹配(例如解压缩输出的大小等)。
老实说,我不确定为什么会发生这种情况。我本来预计会出现一些更明显的错误,但这个错误似乎很随机。肯定是压缩的。并且单线程和多线程程序之间的前几个字节(当然是在标头之后)通常是相同的,所以我认为我没有乱序连接(加上 executor.get() 函数应该处理) .
我只是难过。我知道 gzip 可以解压缩连接的流。我实际上将我的输入分成两半并分别输出,然后将它们组合到我的单线程程序中,它解压缩得很好。
作为记录,我只是在一个包含 328 个“A”字符的文件上尝试过,所以它不是很大。单个线程的 GZIPOutputStream 的 hexdump 是
0000000 8b1f 0008 0000 0000 0000 7472 581c 0000
0000010 0000 ffff 681a 0004 0000 ffff 21a2 02e2
0000020 0000 ff00 03ff a800 5bff 5c79 0001 0000
对于多线程来说
0000000 8b1f 0008 0000 0000 0000 7472 19a4 22e0
0000010 1146 0000 ff00 03ff 7500 5f6c 80d1 0000
0000020 1f00 088b 0000 0000 0000 a200 e221 4622
0000030 0011 0000 ffff 0003 6c75 d15f 0080 0000
0000040 8b1f 0008 0000 0000 0000 21a2 02e2 0000
0000050 ff00 03ff 8a00 193b 5c21 0000 0000
他们很不一样。
哇,这最终真的很长。对于那个很抱歉。只是真的很困惑和卡住。