Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/44.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中解压缩GZip字符串_Java_Gzip - Fatal编程技术网

在Java中解压缩GZip字符串

在Java中解压缩GZip字符串,java,gzip,Java,Gzip,我可以找到很多函数来解压GZip文件,但是如何解压GZip字符串呢 我正试图解析一个HTTP响应,其中响应体是用GZip压缩的。但是,整个响应只是存储在一个字符串中,因此该字符串的一部分包含二进制字符 我正在尝试使用: byte responseBodyBytes[] = responseBody.getBytes(); ByteArrayInputStream bais = new ByteArrayInputStream(responseBodyBytes); GZIPInputStrea

我可以找到很多函数来解压GZip文件,但是如何解压GZip字符串呢


我正试图解析一个HTTP响应,其中响应体是用GZip压缩的。但是,整个响应只是存储在一个字符串中,因此该字符串的一部分包含二进制字符

我正在尝试使用:

byte responseBodyBytes[] = responseBody.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(responseBodyBytes); 
GZIPInputStream gzis = new GZIPInputStream(bais);

但这只是抛出了一个异常:java.io.IOException:不是GZIP格式的

没有GZIP字符串这样的东西。GZip是二进制的,字符串是文本

如果要压缩字符串,需要先将其转换为二进制-例如,使用链接到压缩
OutputStreamWriter
OutputStream
(例如a)

同样,要读取数据,您可以使用链接到解压缩
InputStream
(例如a)的
InputStream读取器


阅读器
轻松阅读的一种方法是使用from或类似的库。

理想情况下,您应该使用高级库来处理这些内容。这样,每当发布新版本的HTTP时,库维护人员都希望为您完成所有艰苦的工作,您只需要更新版本的库

除此之外,尝试自己做这件事是一种很好的锻炼

假设您正在从TCP套接字以字节流的形式读取HTTP响应。如果没有gzip编码,那么将整个响应放入一个字符串就可以了。然而,“contentencoding:gzip”头的存在意味着响应主体(正如您所指出的)将是二进制的

您可以将响应正文的开头标识为字符串序列“\r\n\r\n”(或4个字节0x0d、0x0a、0x0d、0x0a)第一次出现后的第一个字节

gzip编码有一个特殊的头,您应该测试前3个正文字节:

                byte[] buf;  // from the HTTP Response stream
                // ... insert code here to populate buf from HTTP Response stream
                // ...
                int bodyLen = 1234;  // populate this value from 'Content-length' header
                int bodyStart = 123; // index of byte buffer where body starts
                if (bodyLen > 4 && buf[bodyStart] == 0x1f && buf[bodyStart + 1] == (byte) 0x8b && buf[bodyStart + 2] == 0x08) {
                    // gzip compressed body
                    ByteArrayInputStream bais = new ByteArrayInputStream(buf);
                    if (bodyStart > 0) bais.skip(bodyStart);

                    // Decompress the bytes
                    byte[] decompressedBytes = new byte[bodyLen * 4];
                    int decompressedDataLength = 0;
                    try {
                        // note: replace this try-catch with try-with-resources here where possible
                        GZIPInputStream gzis = new GZIPInputStream(bais);
                        decompressedDataLength = gzis.read(decompressedBytes);
                        gzis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
如果前3个字节与magic GZIP头值不匹配,则GZIPInputStream会产生“Not in GZIP format”(不在GZIP格式中)错误,因此测试这些字节将有助于解决特定问题

GZIP格式中还有一个CRC校验和,但是如果该校验和丢失或不正确,您应该会看到另一个错误。

这可能有帮助:

try (final GZIPInputStream gzipInput = new GZIPInputStream(new ByteArrayInputStream(compressedByteArray));
        final StringWriter stringWriter = new StringWriter()) {
        org.apache.commons.io.IOUtils.copy(gzipInput, stringWriter, "UTF_8");
        String decodedString = stringWriter.toString();
    } catch (IOException e) {
        throw new UncheckedIOException("Error while decompression!", e);
    }

我正试图解析一个HTTP响应,其中响应体是用GZip压缩的。但是,整个响应只是存储在一个字符串中,因此该字符串的一部分包含二进制字符。你是说不可能将这个“GZip字符串”转换成文本字符串吗?@Matt:你不应该首先将响应存储在字符串中。如果它是二进制的,就不应该是文本,除非它是base64。“字符串的一部分包含二进制数据”的概念实际上不起作用。听起来你需要改变你的方法。响应最初是以字节[]表示的,所以我只有这些。我能用这个吗?@Jon Skeet我现在也有同样的问题。您是否建议将响应存储在
字节[]
?@Amir:我不知道您想做什么,所以很难说。我建议你在一个新问题中加入更多的上下文。这能回答你的问题吗?