我想我错过了很简单的事情。我有一个字节数组,使用Deflater:
将溢出的数据写入其中deflate(outData, 0, BLOCK_SIZE, SYNC_FLUSH)
我不仅仅使用GZIPOutputStream的原因是因为有4个线程(变量),每个线程都被赋予一个数据块,每个线程在将压缩数据存储到全局字节数组之前压缩它自己的块。如果我使用GZIPOutputStream它会混淆格式,因为每个小块都有一个标题和预告片,它是自己的gzip数据(我只想压缩它)。
所以最后,我得到了这个byteArray,outData,它保存了我所有的压缩数据,但我不确定如何包装它。 GZIPOutputStream从具有未压缩数据的缓冲区写入,但此数组全部已设置。它已经被压缩了,我只是试图弄清楚如何将它变成一个表格。
编辑:好的,我的措辞不好。我将它写入输出,而不是文件,以便在需要时可以重定向。一个非常简单的例子是cat file.txt | java Jzip | gzip -d | cmp file.txt
应该返回0.现在的问题是,如果我将这个字节数组按原样写入输出,它只是“原始”压缩数据。我认为gzip需要所有这些额外的信息。
如果有替代方法,那就没问题了。这样的全部原因是因为我需要使用多个线程。否则我只会调用GZIPOutputStream。
DOUBLE EDIT:由于评论提供了很多好的见解,另一种方法是我只有一堆未压缩的数据块,这些数据块最初是一个长流。如果gzip可以读取连接流,如果我接受了这些块(并按顺序保存它们)并将每个块分配给一个在自己的块上调用GZIPOutputStream的线程,然后取结果并连接它们。实质上,每个块现在都有标题,压缩信息和预告片。如果我连接它们,gzip会认识到吗?
示例:
cat file.txt
Hello world! How are you? I'm ready to set fire to this assignment.
java Testcase < file.txt > file.txt.gz
所以我从输入中接受它。在程序内部,流被分成 “你好,世界!” “你好吗?” “我准备放火烧这个任务”(它们不是字符串,它只是一个字节数组!这只是插图)
所以我有三个字节块,都是未压缩的。我将每个块都给了一个使用
的线程public static class DGZIPOutputStream extends GZIPOutputStream
{
public DGZIPOutputStream(OutputStream out, boolean flush) throws IOException
{
super(out, flush);
}
public void setDictionary(byte[] b)
{
def.setDictionary(b);
}
public void updateCRC(byte[] input)
{
crc.update(input);
}
}
正如你所看到的,这里唯一的事情就是我将flush设置为SYNC_FLUSH,这样我就可以正确对齐并能够设置字典。如果每个线程都使用DGZIPOutputStream(我已经测试了它并且它适用于一个长连续输入),并且我连接了这三个块(现在用头和尾部压缩),gzip -d file.txt.gz工作?
如果这太奇怪了,请完全忽略字典。这并不重要。我只是把它添加进去了。
答案 0 :(得分:6)
如果在使用nowrap
(原文如此)构造函数时将Deflater
设置为true,则结果为raw deflate。否则它是zlib,你必须剥离zlib头和预告片。对于答案的其余部分,我假设nowrap
是真的。
要将完整的,已终止的deflate流包装为gzip流,您需要预先添加十个字节:
"\x1f\x8b\x08\0\0\0\0\0\0\xff"
(抱歉 - C格式,你需要转换为Java八进制)。您还需要以小端顺序附加四字节CRC,然后以小端顺序附加四字节总未压缩长度模2 ^ 32。鉴于标准Java API中可用的内容,您需要以串行方式计算CRC。它不能并行完成。 zlib确实有一个函数来组合并行计算的单独的CRC,但是没有用Java公开。
请注意,我说了一个完整的,终止的deflate流。制作具有并行放气任务的其中一个需要一些小心。您需要使n-1
未终止的deflate流和一个最终终止的deflate流并连接这些流。最后一个是正常的。需要使用同步刷新终止另一个n-1
,以便在字节边界上结束每个{1}}并且不将其标记为流的结尾。为此,您使用deflate
和flush参数SYNC_FLUSH
。不要在finish()
上使用{{1}}。
为了更好地进行压缩,您可以在每个块上使用setDictionary
和前一个块的最后一个32K。
答案 1 :(得分:0)
如果您想在文件中写outdata
,可以写成:
GZIPOutputStream outStream= new GZIPOutputStream(new FileOutputStream("fileName"));
outStream.write(outData, 0, outData.length);
outStream.close();
或者只需使用java.io.FileOutputStream
来写:
FileOutputStream outStream= new FileOutputStream("fileName");
outStream.write(outData, 0, outData.length);
outStream.close();
答案 2 :(得分:0)
您只想将字节数组 - 按原样 - 写入文件?
您可以使用Apache Commons:
FileOutputStream fos = new FileOutputStream("yourFilename");
fos.write(outData);
fos.close():
或普通的旧Java:
BufferedOutputStream bs = null;
try {
FileOutputStream fs = new FileOutputStream(new File("yourFilename"));
bs = new BufferedOutputStream(fs);
bs.write(outData);
bs.close();
} catch (Exception e) {
//please handle this
}
if (bs != null) try {
bs.close();
} catch (Exception e) {
//please handle this
}