gpt4 book ai didi

Java:为 GZIPOutputStream 的 Deflater 使用 setDictionary 时出现 CRC 错误

转载 作者:行者123 更新时间:2023-11-30 11:47:43 26 4
gpt4 key购买 nike

我正在尝试从标准输入中获取数据流,一次压缩一个 128 字节 block ,然后将其输出到标准输出。 (例如:“cat file.txt | java Dict | gzip -d | cmp file.txt”,其中 file.txt 只包含一些 ASCII 字符。)

我还需要为每个后续 block 使用从每个先前 128 字节 block 的末尾获取的 32 字节字典。 (第一个 block 使用它自己的前 32 个字节作为它的字典。)当我根本不设置字典时,压缩工作正常。但是,当我设置字典时,gzip 在尝试解压缩数据时给我一个错误:“gzip: stdin: invalid compressed data--crc error”。

我已经尝试添加/更改代码的几个部分,但到目前为止没有任何效果,而且我还没有通过 Google 找到解决方案。

我试过...

  • 在代码底部附近的“def.setDictionary(b)”之前添加“def.reset()”不起作用。
  • 仅在第一个 block 之后为 block 设置字典是行不通的。 (第一个 block 不使用字典。)
  • 在 compressor.write(input, 0, bytesRead) 之前或之后使用“输入”数组调用 updateCRC 不起作用。

我真的很感激任何建议 - 有什么明显的我遗漏或做错了吗?

这是我的 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: unexpected end of file”。所以一定要确保 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

关于Java:为 GZIPOutputStream 的 Deflater 使用 setDictionary 时出现 CRC 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9186347/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com