我正在尝试从标准输入数据流,一次压缩一个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);
}
}
}
答案 0 :(得分:1)
我不完全知道zlib内部算法的工作原理,但根据我对DictGZIPOutputStream
的理解,当你调用write()方法时,在写入之后,它会为该字节数组更新它的crc。因此,如果再次在代码中再次调用updateCRC()
,那么随着crc更新两次,事情就会出错。然后当执行gzip -d时,由于前两次crc更新,gzip会抱怨“压缩数据无效 - crc错误”
我还注意到你在使用后没有关闭压缩机。当我执行上面粘贴的代码时,它给出了错误“gzip:stdin:意外的文件结束”。所以总是确保刷新方法和最后调用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