以gzip格式包装缩小的数据

use*_*900 1 java multithreading gzip concatenation deflate

我想我错过了很简单的事情.我有一个字节数组,使用Deflater保存写入其中的缩小数据:

deflate(outData, 0, BLOCK_SIZE, SYNC_FLUSH)
Run Code Online (Sandbox Code Playgroud)

我不仅使用GZIPOutputStream的原因是因为有4个线程(变量),每个线程都被赋予一个数据块,每个线程在将压缩数据存储到全局字节数组之前压缩它自己的块.如果我使用GZIPOutputStream它会混淆格式,因为每个小块都有一个标题和预告片,它是自己的gzip数据(我只想压缩它).

所以最后,我得到了这个byteArray,outData,它保存了我所有的压缩数据,但我不确定如何包装它.GZIPOutputStream从具有未压缩数据的缓冲区写入,但此数组全部已设置.它已经被压缩了,我只是试图弄清楚如何将它变成一个表格.

编辑:好的,我的措辞不好.我将它写入输出,而不是文件,以便在需要时可以重定向.一个非常简单的例子是

cat file.txt | java Jzip | gzip -d | cmp file.txt
Run Code Online (Sandbox Code Playgroud)

应该返回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
Run Code Online (Sandbox Code Playgroud)

所以我从输入中接受它.在程序内部,流被分成"Hello world!"."你好吗?" "我准备放火烧这个任务"(它们不是字符串,它只是一个字节数组!这只是插图)

所以我有三个字节块,都是未压缩的.我将每个块都给了一个使用的线程

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);
    }                       
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,这里唯一的事情就是我将flush设置为SYNC_FLUSH,这样我就可以正确对齐并能够设置字典.如果每个线程都使用DGZIPOutputStream(我已经测试了它并且它适用于一个长连续输入),并且我连接了这三个块(现在用头和尾部压缩),gzip -d file.txt.gz工作?

如果这太奇怪了,请完全忽略字典.这并不重要.我刚刚在它的时候添加了它.

Mar*_*ler 6

如果nowrap在使用Deflater(原文如此)构造函数时设置为true ,则结果为raw deflate.否则它是zlib,你必须剥离zlib头和预告片.对于答案的其余部分,我假设nowrap是真的.

要将完整的,已终止的deflate流包装为gzip流,您需要预先添加十个字节:

"\x1f\x8b\x08\0\0\0\0\0\0\xff"
Run Code Online (Sandbox Code Playgroud)

(抱歉 - C格式,你需要转换为Java八进制).您还需要以小端顺序附加四字节CRC,然后以小端顺序附加四字节总未压缩长度模2 ^ 32.鉴于标准Java API中可用的内容,您需要以串行方式计算CRC.它不能并行完成. zlib确实有一个函数来组合并行计算的单独的CRC,但是没有在Java中公开.

请注意,我说完整的,终止的deflate流.制作具有并行放气任务的其中一个需要一些小心.你需要制作n-1未端接的deflate流和一个最终终止的deflate流并连接它们.最后一个是正常的.另一个n-1需要使用同步刷新终止,以便在字节边界上结束每个并且不将其标记为流的结尾.为此,请使用deflateflush参数SYNC_FLUSH.不要使用finish()那些.

为了更好的压缩,您可以setDictionary在每个块上使用前一个块的最后32K.