【问题标题】:Java: Error creating a GZIPInputStream: Not in GZIP formatJava:创建 GZIPInputStream 时出错:不是 GZIP 格式
【发布时间】:2013-01-22 19:50:48
【问题描述】:

我正在尝试使用以下 Java 代码来压缩和解压缩字符串。但是从新的 ByteArrayInputStream 对象中创建新的 GZipInputStream 对象的行会引发“java.util.zip.ZipException: Not in GZIP format”异常。有谁知道如何解决这个问题?

        String orig = ".............";

        // compress it
        ByteArrayOutputStream baostream = new ByteArrayOutputStream();
        OutputStream outStream = new GZIPOutputStream(baostream);
        outStream.write(orig.getBytes());
        outStream.close();
        String compressedStr = baostream.toString();

        // uncompress it
        InputStream inStream = new GZIPInputStream(new ByteArrayInputStream(compressedStr.getBytes()));
        ByteArrayOutputStream baoStream2 = new ByteArrayOutputStream();
        byte[] buffer = new byte[8192];
        int len;
        while((len = inStream.read(buffer))>0)
            baoStream2.write(buffer, 0, len);
        String uncompressedStr = baoStream2.toString();

【问题讨论】:

    标签: java compression gzip gzipinputstream


    【解决方案1】:

    混合Stringbyte[];那永远不适合。并且仅适用于具有相同编码的相同操作系统。并非每个byte[] 都可以转换为String,转换回来可能会给出其他字节。

    compressedBytes 不必代表字符串。

    getBytesnew String中显式设置编码。

        String orig = ".............";
    
        // Compress it
        ByteArrayOutputStream baostream = new ByteArrayOutputStream();
        OutputStream outStream = new GZIPOutputStream(baostream);
        outStream.write(orig.getBytes("UTF-8"));
        outStream.close();
        byte[] compressedBytes = baostream.toByteArray(); // toString not always possible
    
        // Uncompress it
        InputStream inStream = new GZIPInputStream(
                new ByteArrayInputStream(compressedBytes));
        ByteArrayOutputStream baoStream2 = new ByteArrayOutputStream();
        byte[] buffer = new byte[8192];
        int len;
        while ((len = inStream.read(buffer)) > 0) {
            baoStream2.write(buffer, 0, len);
        }
        String uncompressedStr = baoStream2.toString("UTF-8");
    
        System.out.println("orig: " + orig);
        System.out.println("unc:  " + uncompressedStr);
    

    【讨论】:

      【解决方案2】:

      Joop 似乎有解决方案,但我觉得我必须添加以下内容: 一般的压缩,特别是 GZIP 会产生 binary 流。 您不得尝试从此流中构造字符串 - 它中断。

      如果您需要将其转换为纯文本表示,请查看 Base64 编码、十六进制编码、哎呀,甚至是简单的二进制编码。

      简而言之,String 对象用于人类阅读的内容。字节数组(和许多其他东西)用于机器读取的东西。

      【讨论】:

        【解决方案3】:

        您使用默认平台编码(可能是 UTF-8)将 baostream 编码为字符串。您应该使用 baostream.getBytes() 处理二进制数据,而不是字符串。

        如果您坚持使用字符串,请使用 8 位编码,例如。 baostream.toString("ISO-8859-1"),然后用相同的字符集读回。

        【讨论】:

        • 即使在两端都指定了字符编码,将字节直接存储到字符串中也会变得很冒险。使用字符串的更好方法可能是使用二进制数据的 Base64 编码。 Apache Commons 编解码器为Base64 encoding and decoding 提供了一个非常好的类
        • 另外 UTF-8 绝对是 8 位编码。
        • “8 位编码”的通俗意思是每个代码 unit 正好是 8 位,这绝对不是 UTF-8 在 ascii 以上的代码点中的情况.但是,是的,编码的滥用会间接导致术语的滥用,而且您对 base64 编码的建议要好得多。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-13
        • 1970-01-01
        • 2021-08-23
        相关资源
        最近更新 更多