GZIPInputStream转换为字符串

36

我想将一个HTTP响应的gzip压缩体转换为纯文本。我已经取得了这个响应的字节数组并将其转换为ByteArrayInputStream。然后我将其转换为GZIPInputStream。现在,我想读取GZIPInputStream并将最终解压缩的HTTP响应体作为纯文本字符串存储。

这段代码将把最终解压缩的内容存储在OutputStream中,但我想要将内容存储为字符串:

public static int sChunk = 8192;
ByteArrayInputStream bais = new ByteArrayInputStream(responseBytes);
GZIPInputStream gzis = new GZIPInputStream(bais);
byte[] buffer = new byte[sChunk];
int length;
while ((length = gzis.read(buffer, 0, sChunk)) != -1) {
        out.write(buffer, 0, length);
}

正如我在你的另一个问题(https://dev59.com/_nA65IYBdhLWcg3wzyBl)中所说,你需要使用InputStreamReader。 - Jon Skeet
请查看此链接:https://dev59.com/oGw15IYBdhLWcg3wSJo3 - Bobs
这个回答解决了你的问题吗?在Java中解压GZip字符串 - Yash
8个回答

50

要从InputStream中解码字节,可以使用InputStreamReader。然后,使用BufferedReader可以逐行读取流。

您的代码将如下所示:

ByteArrayInputStream bais = new ByteArrayInputStream(responseBytes);
GZIPInputStream gzis = new GZIPInputStream(bais);
InputStreamReader reader = new InputStreamReader(gzis);
BufferedReader in = new BufferedReader(reader);

String readed;
while ((readed = in.readLine()) != null) {
    System.out.println(readed);
}

1
不要忘记在ISR构造函数中指定编码以正确解释字节! :) - helios
3
除了可能存在编码错误外,请注意这种方法会忽略换行符。因此,如果您希望在输出中保留换行符,则确实需要自己将它们明确地添加到 output 中(例如使用 PrintWriter#println()BufferedWriter#newLine())。或者采用另一个答案中所示的 char[] buffer 循环方法,该方法不会忽略换行符。 - BalusC

34
你应该将响应作为 InputStream 而不是 byte[] 获取。然后,你可以使用 GZIPInputStream 解压缩它,并使用InputStreamReader 读取字符数据,最后将其作为字符数据写入String 中,使用 StringWriter
String body = null;
String charset = "UTF-8"; // You should determine it based on response header.

try (
    InputStream gzippedResponse = response.getInputStream();
    InputStream ungzippedResponse = new GZIPInputStream(gzippedResponse);
    Reader reader = new InputStreamReader(ungzippedResponse, charset);
    Writer writer = new StringWriter();
) {
    char[] buffer = new char[10240];
    for (int length = 0; (length = reader.read(buffer)) > 0;) {
        writer.write(buffer, 0, length);
    }
    body = writer.toString();
}

// ...

参考资料:


如果你的最终目的是解析响应作为 HTML,那么我强烈推荐使用像Jsoup这样的HTML解析器。然后就像这样简单:

String html = Jsoup.connect("http://google.com").get().html();

10

使用try-with-resources惯用语法(可以在代码块结束时自动关闭任何在try(...)中打开的资源),使代码更加简洁。

使用Apache IOUtils将inputStream转换为String,使用默认字符集。

import org.apache.commons.io.IOUtils;
public static String gzipFileToString(File file) throws IOException {
    try(GZIPInputStream gzipIn = new GZIPInputStream(new FileInputStream(file))) {
        return IOUtils.toString(gzipIn);
    }
}

1
你应该添加一些解释说明为什么这段代码可以工作 - 你也可以在代码本身中添加注释。以其当前的形式,它没有提供任何解释,这可能有助于其他社区成员理解你是如何解决/回答问题的。 - ishmaelMakitla
1
这是最简单的答案。为什么要自己处理缓冲区、字节、关闭等等,当它可以只用两行代码解决呢?而且现在几乎每个项目都会在某处使用IOUtils - membersound

2
使用Apache Commons将GzipInputStream转换为byteArray。
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import org.apache.commons.io.IOUtils;

public static byte[] decompressContent(byte[] pByteArray) throws IOException {
        GZIPInputStream gzipIn = null;
        try {
            gzipIn = new GZIPInputStream(new ByteArrayInputStream(pByteArray));
            return IOUtils.toByteArray(gzipIn);
        } finally {
            if (gzipIn != null) {
                gzipIn.close();
            }
        }

要将未压缩的字节数组内容转换为字符串,请按照以下方式进行操作:
String uncompressedContent = new String(decompressContent(inputStream));

1

1

GZipwiki 是一种文件格式和软件应用程序,用于文件的压缩和解压缩。gzip 是一个单文件/流无损数据压缩实用程序,生成的压缩文件通常具有后缀.gz

字符串(明文) ➢ 字节 ➤ GZip-Data(压缩) ➦ 字节 ➥ 字符串(解压)

String zipData = "Hi Stackoverflow and GitHub";
        
// String to Bytes
byte[] byteStream = zipData.getBytes();
System.out.println("String Data:"+ new String(byteStream, "UTF-8"));

// Bytes to Compressed-Bytes then to String.
byte[] gzipCompress = gzipCompress(byteStream);
String gzipCompressString = new String(gzipCompress, "UTF-8");
System.out.println("GZIP Compressed Data:"+ gzipCompressString);

// Bytes to DeCompressed-Bytes then to String.
byte[] gzipDecompress = gzipDecompress(gzipCompress);
String gzipDecompressString = new String(gzipDecompress, "UTF-8");
System.out.println("GZIP Decompressed Data:"+ gzipDecompressString);

GZip-Bytes(压缩) ➥ 文件 (*.gz) ➥ 字符串(解压)

GZip 的文件扩展名为 .gz,Internet 媒体类型为 application/gzip

File textFile = new File("C:/Yash/GZIP/archive.gz.txt");
File zipFile = new File("C:/Yash/GZIP/archive.gz");
org.apache.commons.io.FileUtils.writeByteArrayToFile(textFile, byteStream);
org.apache.commons.io.FileUtils.writeByteArrayToFile(zipFile, gzipCompress);

FileInputStream inStream = new FileInputStream(zipFile);
byte[] fileGZIPBytes = IOUtils.toByteArray(inStream);
byte[] gzipFileDecompress = gzipDecompress(fileGZIPBytes);
System.out.println("GZIPFILE Decompressed Data:"+ new String(gzipFileDecompress, "UTF-8"));

以下函数用于压缩和解压缩。
public static byte[] gzipCompress(byte[] uncompressedData) {
    byte[] result = new byte[]{};
    try (
        ByteArrayOutputStream bos = new ByteArrayOutputStream(uncompressedData.length);
        GZIPOutputStream gzipOS = new GZIPOutputStream(bos)
        ) {
        gzipOS.write(uncompressedData);
        gzipOS.close(); // You need to close it before using ByteArrayOutputStream
        result = bos.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return result;
}

public static byte[] gzipDecompress(byte[] compressedData) {
    byte[] result = new byte[]{};
    try (
        ByteArrayInputStream bis = new ByteArrayInputStream(compressedData);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        GZIPInputStream gzipIS = new GZIPInputStream(bis)
        ) {
        //String gZipString= IOUtils.toString(gzipIS);
        byte[] buffer = new byte[1024];
        int len;
        while ((len = gzipIS.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        result = bos.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return result;
}

0
import java.io.*;
import java.util.zip.*;

public class Ex1 {

    public static void main(String[] args) throws Exception{
        String str ;

        H h1 = new H();
        h1.setHcfId("PH12345658");
        h1.setHcfName("PANA HEALTH ACRE FACILITY");

        str = h1.toString();
        System.out.println(str);

        if (str == null || str.length() == 0) {
            return ;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream(str.length());
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        gzip.write(str.getBytes());
        gzip.close();
        out.close();

        String s =  out.toString() ;
        System.out.println( s );
        byte[] ba = out.toByteArray();
        System.out.println( "---------------BREAK-------------" );

        ByteArrayInputStream in = new ByteArrayInputStream(ba);
        GZIPInputStream gzis = new GZIPInputStream(in);
        InputStreamReader reader = new InputStreamReader(gzis);
        BufferedReader pr = new BufferedReader(reader);

        String readed;
        while ((readed = pr.readLine()) != null) {
            System.out.println(readed);
        }

        //Close all the streams
    }

}

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接