Java java.io.IOException : Not in GZIP format 异常

标签 java gzipinputstream

我搜索了一个如何在 Java 中压缩字符串的示例。

我有一个压缩然后解压的功能。压缩似乎工作正常:

   public static String encStage1(String str)
   {
      String format1 = "ISO-8859-1";
      String format2 = "UTF-8";
      if (str == null || str.length() == 0)
      {
         return str;
      }
      System.out.println("String length : " + str.length());
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      String outStr = null;
      try
      {
         GZIPOutputStream gzip = new GZIPOutputStream(out);
         gzip.write(str.getBytes());
         gzip.close();
         outStr = out.toString(format2);
         System.out.println("Output String lenght : " + outStr.length());
      } catch (Exception e)
      {
                  e.printStackTrace();

      }
      return outStr;
   }

但相反的是提示字符串不是 GZIP 格式,即使我从 encStage1 直接返回到 decStage3:

   public static String decStage3(String str)
   {
      if (str == null || str.length() == 0)
      {
         return str;
      }
      System.out.println("Input String length : " + str.length());
      String outStr = "";
      try
      {
         String format1 = "ISO-8859-1";
         String format2 = "UTF-8";
         GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(str.getBytes(format2)));
         BufferedReader bf = new BufferedReader(new InputStreamReader(gis, format2));
         String line;
         while ((line = bf.readLine()) != null)
         {
            outStr += line;
         }
         System.out.println("Output String lenght : " + outStr.length());
      } catch (Exception e)
      {
         e.printStackTrace();
      }
      return outStr;
   }

当我使用从 encStage1 返回的字符串调用时出现此错误:

   public String encIDData(String idData)
   {
      String tst = "A simple test string";
      System.out.println("Enc 0: " + tst);
      String stg1 = encStage1(tst);
      System.out.println("Enc 1: " + toHex(stg1));
      String dec1 = decStage3(stg1);
      System.out.println("unzip: " + toHex(dec1));
   }

输出/错误:

Enc 0: A simple test string
String length : 20
Output String lenght : 40
Enc 1: 1fefbfbd0800000000000000735428efbfbdefbfbd2defbfbd495528492d2e51282e29efbfbdefbfbd4b07005aefbfbd21efbfbd14000000
Input String length : 40
java.io.IOException: Not in GZIP format
    at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:137)
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:58)
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:68)

最佳答案

一个小错误是:

     gzip.write(str.getBytes());

采用默认平台编码,在 Windows 上永远不会是 ISO-8859-1。更好:

     gzip.write(str.getBytes(format1));

您可以考虑使用“Cp1252”、Windows Latin-1(对于某些欧洲语言),而不是“ISO-8859-1”、Latin-1。这会添加引号等逗号。

主要错误是将压缩字节转换为字符串。 Java 将二进制数据(byte[]、InputStream、OutputStream)与文本(String、char、Reader、Writer)分开,后者在内部始终以 Unicode 格式保存。字节序列不需要是有效的 UTF-8。您可以通过将字节转换为单字节编码(例如 ISO-8859-1)来逃脱。

最好的办法是

     gzip.write(str.getBytes(StandardCharsets.UTF_8));

所以你有完整的 Unicode,每个脚本都可以组合。

并解压缩到 ByteArrayOutputStreamnew String(baos.toByteArray(), StandardCharsets.UTF_8)。 在具有 UTF-8 的 InputStreamReader 上使用 BufferedReader 也可以,但是 readLine 会丢弃换行符

outStr += line + "\r\n"; // Or so.

干净的答案:

public static byte[] encStage1(String str) throws IOException
{
   try (ByteArrayOutputStream out = new ByteArrayOutputStream())
   {
       try (GZIPOutputStream gzip = new GZIPOutputStream(out))
       {
           gzip.write(str.getBytes(StandardCharsets.UTF_8));
       }
       return out.toByteArray();
       //return out.toString(StandardCharsets.ISO_8859_1);
       // Some single byte encoding
   }
}

public static String decStage3(byte[] str) throws IOException
{
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   try (GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(str)))
   {
       int b;
       while ((b = gis.read()) != -1) {
           baos.write((byte) b);
       }
   }
   return new String(baos.toByteArray(), StandardCharset.UTF_8);
}

关于Java java.io.IOException : Not in GZIP format 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25310193/

相关文章:

Android:读取 ASSETS 文件夹中的 GZIP 文件

java - 我如何在我在java应用程序中创建的Neo4j Web管理中查看索引及其节点?

C# MemoryStream & GZipInputStream : Can't . 读取超过 256 个字节

java - 这是 Java GZipInputStream 类中的错误吗?

java - 一次性将 gzip 文件读取到 byte[]

java.io.EOFException : Unexpected end of ZLIB input stream reading gzip encoded website

java - Firebase Android 通过子键获取值

java - 从文本文件中读取票证数据

java - 计算指数增长系列中的值之和

Java 8 List<V> 到 Map<K, V> 覆盖重复键