![](/img/trans.png)
[英]Java- concatenating compressed data with Deflater or GZIPOutputStream
[英]Java: CRC error when using setDictionary for GZIPOutputStream's Deflater
我正在嘗試從標准輸入中獲取數據流,一次將其壓縮為一個128字節塊,然后將其輸出到標准輸出中。 (例如:“ cat file.txt | Java Dict | gzip -d | cmp file.txt”,其中file.txt僅包含一些ASCII字符。)
對於每個后續塊,我還需要使用從每個先前128字節塊的末尾獲取的32字節字典。 (第一個塊使用其自己的前32個字節作為其字典。)當我完全不設置字典時,壓縮效果很好。 但是,當我設置字典時,gzip嘗試解壓縮數據時出現錯誤:“ gzip:stdin:無效的壓縮數據--crc錯誤”。
我曾嘗試添加/更改代碼的幾個部分,但到目前為止沒有任何效果,而且我在Google上找不到任何解決方案。
我試過了...
我真的很感謝任何建議-有什么明顯的我想念或做錯了嗎?
這就是我的Dict.java文件中的內容:
import java.io.*;
import java.util.zip.GZIPOutputStream;
public class Dict {
protected static final int BLOCK_SIZE = 128;
protected static final int DICT_SIZE = 32;
public static void main(String[] args) {
InputStream stdinBytes = System.in;
byte[] input = new byte[BLOCK_SIZE];
byte[] dict = new byte[DICT_SIZE];
int bytesRead = 0;
try {
DictGZIPOuputStream compressor = new DictGZIPOuputStream(System.out);
bytesRead = stdinBytes.read(input, 0, BLOCK_SIZE);
if (bytesRead >= DICT_SIZE) {
System.arraycopy(input, 0, dict, 0, DICT_SIZE);
compressor.setDictionary(dict);
}
do {
compressor.write(input, 0, bytesRead);
compressor.flush();
if (bytesRead == BLOCK_SIZE) {
System.arraycopy(input, BLOCK_SIZE-DICT_SIZE-1, dict, 0, DICT_SIZE);
compressor.setDictionary(dict);
}
bytesRead = stdinBytes.read(input, 0, BLOCK_SIZE);
} while (bytesRead > 0);
compressor.finish();
}
catch (IOException e) {e.printStackTrace();}
}
public static class DictGZIPOuputStream extends GZIPOutputStream {
public DictGZIPOuputStream(OutputStream out) throws IOException {
super(out);
}
public void setDictionary(byte[] b) {
def.setDictionary(b);
}
public void updateCRC(byte[] input) {
crc.update(input);
}
}
}
我不完全知道zlib算法在內部的工作原理,但是基於對DictGZIPOutputStream
理解,當您調用write()方法時,在寫入之后,它將為該字節數組更新其crc。 因此,如果您再次在代碼中再次調用updateCRC()
,那么由於crc被更新了兩次,事情就變得錯誤了。 然后,當執行gzip -d時,由於前兩次crc更新,gzip將抱怨“無效的壓縮數據-crc錯誤”
我還注意到,使用壓縮機后您沒有關閉壓縮機。 當我執行上面粘貼的代碼時,它給出了錯誤“ gzip:stdin:文件意外結束”。 因此,請務必確保在最后調用了flush方法和 close方法。 話雖如此,我有以下幾點,
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
public class Dict
{
protected static final int BLOCK_SIZE = 128;
protected static final int DICT_DIZE = 32;
public static void main(String[] args)
{
InputStream stdinBytes = System.in;
byte[] input = new byte[BLOCK_SIZE];
byte[] dict = new byte[DICT_DIZE];
int bytesRead = 0;
try
{
DictGZIPOutputStream compressor = new DictGZIPOutputStream(System.out);
bytesRead = stdinBytes.read(input, 0, BLOCK_SIZE);
if (bytesRead >= DICT_DIZE)
{
System.arraycopy(input, 0, dict, 0, DICT_DIZE);
}
do
{
compressor.write(input, 0, bytesRead);
if (bytesRead == BLOCK_SIZE)
{
System.arraycopy(input, BLOCK_SIZE-1, dict, 0, DICT_DIZE);
compressor.setDictionary(dict);
}
bytesRead = stdinBytes.read(input, 0, BLOCK_SIZE);
}
while (bytesRead > 0);
compressor.flush();
compressor.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static class DictGZIPOutputStream extends GZIPOutputStream
{
public DictGZIPOutputStream(OutputStream out) throws IOException
{
super(out);
}
public void setDictionary(byte[] b)
{
def.setDictionary(b);
}
public void updateCRC(byte[] input)
{
crc.update(input);
}
}
}
控制台上的測試結果。
$ cat file.txt
hello world, how are you?1e3djw
hello world, how are you?1e3djw adfa asdfas
$ cat file.txt | java Dict | gzip -d | cmp file.txt ; echo $?
0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.