【问题标题】:Using Java Deflater/Inflater with custom dictionary causes IllegalArgumentException将 Java Deflater/Inflater 与自定义字典一起使用会导致 IllegalArgumentException
【发布时间】:2011-08-05 01:44:42
【问题描述】:

以下代码基于javadocs for java.util.zip.Deflater 中给出的示例。我所做的唯一更改是创建一个名为 dict 的字节数组,然后使用 setDictionary(byte[]) 方法在 Deflater 和 Inflater 实例上设置字典。

我看到的问题是,当我使用与 Deflater 完全相同的数组调用 Inflater.setDictionary() 时,我得到了 IllegalArgumentException。

这里是有问题的代码:

import java.util.zip.Deflater;
import java.util.zip.Inflater;

public class DeflateWithDictionary {
    public static void main(String[] args) throws Exception {
        String inputString = "blahblahblahblahblah??";
        byte[] input = inputString.getBytes("UTF-8");
        byte[] dict = "blah".getBytes("UTF-8");

        // Compress the bytes
        byte[] output = new byte[100];
        Deflater compresser = new Deflater();
        compresser.setInput(input);
        compresser.setDictionary(dict);
        compresser.finish();
        int compressedDataLength = compresser.deflate(output);

        // Decompress the bytes
        Inflater decompresser = new Inflater();
        decompresser.setInput(output, 0, compressedDataLength);
        decompresser.setDictionary(dict);  //IllegalArgumentExeption thrown here
        byte[] result = new byte[100];
        int resultLength = decompresser.inflate(result);
        decompresser.end();

        // Decode the bytes into a String
        String outputString = new String(result, 0, resultLength, "UTF-8");
        System.out.println("Decompressed String: " + outputString);
    }
}

如果我尝试在不设置字典的情况下压缩相同的压缩字节,我不会收到错误,但返回的结果是零字节。

为了将自定义字典与 Deflater/Inflater 一起使用,我需要做些什么特别的事情吗?

【问题讨论】:

    标签: java compression zip deflate


    【解决方案1】:

    我实际上是在提出问题时想到了这一点,但我认为无论如何我都应该发布这个问题,这样其他人可能会从我的努力中受益。

    事实证明,您必须在设置输入之后调用一次 inflate(),但在设置字典之前之前。返回的值为 0,然后调用 needsDictionary() 将返回 true。之后,您可以设置字典并再次调用 inflate。

    修改后的代码如下:

    import java.util.zip.Deflater;
    import java.util.zip.Inflater;
    
    public class DeflateWithDictionary {
        public static void main(String[] args) throws Exception {
            String inputString = "blahblahblahblahblah??";
            byte[] input = inputString.getBytes("UTF-8");
            byte[] dict = "blah".getBytes("UTF-8");
    
            // Compress the bytes
            byte[] output = new byte[100];
            Deflater compresser = new Deflater();
            compresser.setInput(input);
            compresser.setDictionary(dict);
            compresser.finish();
            int compressedDataLength = compresser.deflate(output);
    
            // Decompress the bytes
            Inflater decompresser = new Inflater();
            decompresser.setInput(output, 0, compressedDataLength);
            byte[] result = new byte[100];
            decompresser.inflate(result);
            decompresser.setDictionary(dict);
            int resultLength = decompresser.inflate(result);
            decompresser.end();
    
            // Decode the bytes into a String
            String outputString = new String(result, 0, resultLength, "UTF-8");
            System.out.println("Decompressed String: " + outputString);
        }
    }
    

    从 API 设计的角度来看,这似乎非常反直觉和笨拙,所以如果有更好的选择,请赐教。

    【讨论】:

    • needsDictionary()的原因是zlib格式允许在同一个应用程序中使用不同的字典,并在文件头中指明字典的Adler32-checksum。要读取此标头(并允许解压缩端的应用程序选择正确的字典),需要第一次调用 inflate
    • 当我这样做时,我需要在 inflate() 之前设置字典,这很有意义。所以你的例子有些不对劲......
    猜你喜欢
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2018-03-07
    • 2021-09-09
    • 2018-10-09
    • 2017-05-30
    • 2019-09-19
    • 2014-01-28
    相关资源
    最近更新 更多