【问题标题】:GZIPInputStream to StringGZIPInputStream 转字符串
【发布时间】:2011-04-07 08:15:53
【问题描述】:

我正在尝试将 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);
}

【问题讨论】:

标签: java http gzip gzipinputstream


【解决方案1】:

要解码来自 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);
}

【讨论】:

  • 并且不要忘记在 ISR 构造函数中指定编码以正确解释字节! :)
  • 除了潜在的编码错误外,还要注意这种方法会吞下换行符。因此,如果您想在输出中保留换行符,您确实需要自己显式地将它们添加到output(例如使用PrintWriter#println()BufferedWriter#newLine())。或者只是去一个char[] buffer循环方法,如另一个答案所示,它不会吞下换行符。
【解决方案2】:

您应该以InputStream 而不是byte[] 的形式获得响应。然后您可以使用GZIPInputStream 对其进行解压缩并使用InputStreamReader 将其作为字符数据读取,最后使用StringWriter 将其作为字符数据写入String

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,那么我强烈建议您只使用 HTML 解析器,例如 Jsoup。然后就很简单了:

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

【讨论】:

    【解决方案3】:

    使用 try-with-resources 习惯用法(在退出块时自动关闭在 try(...) 中打开的所有资源)以使代码更简洁。

    使用 Apache IOUtils 使用默认 CharSet 将 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);
        }
    }
    

    【讨论】:

    • 你真的应该添加一些解释为什么这个代码应该工作 - 你也可以在代码本身中添加 cmets - 在它的当前形式中,它没有提供任何可以帮助其余部分的解释社区了解您为解决/回答问题所做的工作。
    • 这是最简单的答案。当它可以是 2-liner 时,为什么还要自己处理缓冲区、字节、关闭等?现在几乎每个项目都会在某个地方使用IOUtils
    【解决方案4】:

    使用 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));
    

    【讨论】:

      【解决方案5】:

      您可以使用StringWriter 写入字符串

      【讨论】:

        【解决方案6】:

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

        String(Plain) ➢ 字节 ➤ GZip-Data(Compress) ➦ 字节 ➥ String(Decompress)

        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(Compress) ➥ 文件 (*.gz) ➥ 字符串(Decompress)

        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;
        }
        

        【讨论】:

          【解决方案7】:
          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
              }
          
          }
          

          【讨论】:

            【解决方案8】:

            你也可以

            try (GZIPInputStream gzipIn = new GZIPInputStream(new ByteArrayInputStream(pByteArray)))
            {
            ....
            }
            

            AutoClosable 是个好东西 https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-01-05
              • 1970-01-01
              • 1970-01-01
              • 2019-10-10
              • 2016-01-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多