【问题标题】:GZIP Compression & Decompression IssueGZIP 压缩和解压问题
【发布时间】:2012-09-25 04:37:22
【问题描述】:

您好,我正在使用 GZIP 压缩和解压缩字符串。

得到一些例外!请帮帮我!

protected byte[] CompressInputString(String input_string2)
        throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream(
            input_string2.length());
    System.out.println("Byte Array OS : " + os);
    GZIPOutputStream gos = new GZIPOutputStream(os);
    System.out.println("GZIPOutputStream : " + gos);
    gos.write(input_string2.getBytes());
    System.out.println("GZIPOutputStream get bytes: "
            + input_string2.getBytes());
    gos.close();
    byte[] compressed = os.toByteArray();
    os.close();
    System.out.println("Compressed : " + compressed);
    return compressed;

}

protected String DecompressInputString(byte[] input_to_decode_from_function)
        throws IOException {
    final int BUFFER_SIZE = 32;
    ByteArrayInputStream is = new ByteArrayInputStream(input_to_decode_from_function);
    GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
    StringBuilder string = new StringBuilder();
    byte[] data = new byte[BUFFER_SIZE];
    int bytesRead;
    while ((bytesRead = gis.read(data)) != -1) {
        string.append(new String(data, 0, bytesRead));
    }
    gis.close();
    is.close();
    return string.toString();
}

我的输入是:abcdefghijklmnop

输出是

GZIPOutputStream : java.util.zip.GZIPOutputStream@f38798
GZIPOutputStream get bytes: [B@4b222f
Compressed : [B@b169f8
Compressed File : [B@b169f8

要解压缩,我要输入什么?

如果我将[B@b169f8 作为字符串输入并使用 input.getBytes() 将其转换为字节数组并将其传递给我的解压缩函数,则会引发异常

【问题讨论】:

  • 第一个建议:永远不要在不指定编码的情况下使用String.getBytes()...
  • 那么第二个选项是什么先生,我需要尽快让这个代码滚动!
  • 这不是一个“选项”——它只是问题的部分。有关更多信息,请参阅我的答案。

标签: java gzip compression


【解决方案1】:

如果我将 [B@b169f8 作为字符串输入并使用 INPUT.getBytes() 将其转换为字节数组并将其传递给我的解压缩函数...引发异常

是的 - 因为“[B@b169f8”实际上不是字节数组的内容。这只是在其上调用toString() 的结果;它基本上表明了对象的类型及其哈希。

如果你想以无损的方式将字节数组转换为字符串,则需要使用base64之类的东西。有很多库执行 base64 编码,包括this public domain one

此外,我强烈建议不要使用 String.getBytes()String(byte[], int, int) 构造函数。您应该始终指定编码。读取数据的最简单方法是创建一个包装GZIPInputStreamInputStreamReader,并直接从中读取文本数据。我建议使用 UTF-8 作为初始文本到二进制转换的编码(当然,在解压缩方面也是如此)。

【讨论】:

  • 能否为您的建议添加代码,例如 - 压缩和解压缩函数,请
  • @rolling.stones:不,恐怕我没有时间。我已经解释了问题所在,并给出了指向 base64 编码器/解码器的指针。如果您还有具体的问题,我可以回答。
  • @Jon Skeet:您能否纠正我在下面添加的压缩和解压缩调用评论中的错误!我的压缩看起来不错,输入什么以及如何调用以获得我的输出?
  • 主要问题是,如果此应用程序在 2 台计算机上运行....我压缩 COMP1 上的字符串,我想将此压缩值插入 COMP2 以获取原始字符串补偿2。我应该在 COMP2 中输入什么来解压?
  • @rolling.stones:请停止使用大写字母。您的压缩很好,因为它使用平台默认编码,该编码可能因地而异。在你解决这个问题后,你需要将CompressInputString 返回的二进制数据(顺便说一下,你应该阅读Java 命名约定)传输到另一台计算机。目前,听起来您正试图通过在字节数组上调用 toString 来做到这一点。正如我在回答中解释的那样,这基本上没用。
【解决方案2】:

首先,您在字节数组上使用.toString() 将字节数组转换为字符串,它返回其内存地址的表示,而不是其内容。

如果您确实需要将字节数组表示为介于两者之间的字符串,您将需要一种合理的方式将其表示为字符串。 Base64 是一种合理的方法。

然后,您需要将其转回字节数组,然后再将其送入充气机。

或者,您可以跳过以上两个步骤,将字节数组保留为字节数组,直接将其提供给充气机。

【讨论】:

    【解决方案3】:

    对我来说很好,我试过这样调用你的方法:

    public static void main(String[] args) throws Throwable {
        Test tf = new Test();
        byte[] compressed = tf.CompressInputString("Jimmy");
        System.out.println(Arrays.toString(compressed));
        String s = tf.DecompressInputString(compressed);
        System.out.println(s);//Prints "Jimmy"
    
    }
    

    您能否添加一个如何调用方法的示例,以及任何异常的完整堆栈跟踪?

    【讨论】:

    • 解压 input_string_for_decode = input_to_decode.getText(); input_string_for_decode_bytes = input_string_for_decode .getBytes(); decompressed = DecompressInputString(input_string_for_decode_bytes); lblDecodedString.setText("Decoded Value : " + decompressed);
    • 压缩 input_string_for_encode = input_to_encode.getText().toString(); try { compressed = CompressInputString(input_string_for_encode); lblEncodedString.setText("Encoded Value : " + compressed.toString()); System.out.println("Compressed File : " + compressed); input_to_decode.setText(compressed.toString());
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 2023-03-18
    • 2015-07-14
    相关资源
    最近更新 更多