【问题标题】:Is this a bug in the Java GZipInputStream class?这是 Java GZipInputStream 类中的错误吗?
【发布时间】:2011-07-13 16:40:00
【问题描述】:

我注意到我的一些 gzip 解码代码似乎无法检测到损坏的数据。我认为我已经将问题追溯到 Java GZipInputStream 类。特别是,当您使用单个“读取”调用读取整个流时,损坏的数据似乎不会触发 IOException。如果您在 2 次或更多次调用中读取相同损坏数据的流,则会触发异常。

在考虑提交错误报告之前,我想看看社区的想法。

编辑:我修改了我的例子,因为最后一个没有清楚地说明我认为是什么问题。在这个新示例中,一个 10 字节的缓冲区被压缩,压缩后的缓冲区的一个字节被修改,然后被解压缩。对“GZipInputStream.read”的调用返回 10 作为读取的字节数,这是您对 10 字节缓冲区的期望值。然而,解压缩的缓冲区与原始缓冲区不同(由于损坏)。不会抛出异常。我确实注意到,在读取后调用“可用”返回“1”而不是“0”,如果已达到 EOF,它将返回“0”。

这里是来源:

  @Test public void gzip() {
    try {
      int length = 10;
      byte[] bytes = new byte[]{12, 19, 111, 14, -76, 34, 60, -43, -91, 101};
      System.out.println(Arrays.toString(bytes));

      //Gzip the byte array
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      GZIPOutputStream gos = new GZIPOutputStream(baos);
      gos.write(bytes);
      gos.finish();
      byte[] zipped = baos.toByteArray();

      //Alter one byte of the gzipped array.  
      //This should be detected by gzip crc-32 checksum
      zipped[15] = (byte)(0);

      //Unzip the modified array
      ByteArrayInputStream bais = new ByteArrayInputStream(zipped);
      GZIPInputStream gis = new GZIPInputStream(bais);
      byte[] unzipped = new byte[length];
      int numRead = gis.read(unzipped);
      System.out.println("NumRead: " + numRead);
      System.out.println("Available: " + gis.available());

      //The unzipped array is now [12, 19, 111, 14, -80, 0, 0, 0, 10, -118].
      //No IOException was thrown.
      System.out.println(Arrays.toString(unzipped));

      //Assert that the input and unzipped arrays are equal (they aren't)
      org.junit.Assert.assertArrayEquals(unzipped, bytes);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

【问题讨论】:

  • +1 好问题;写得很好,带有独立、简洁、可运行的例子。这就是为什么你得到这么快的答案:-)

标签: java gzip gzipinputstream


【解决方案1】:

决定运行测试:

你错过了什么。 gis.read(unzipped) 返回 1,因此它只读取了一个字节。你不能抱怨,这不是信息流的尽头。

下一个 read() 抛出 “损坏的 GZIP 预告片”

所以一切都很好! (至少在 GZIPInputStream 中没有错误

【讨论】:

  • +1 打败我 :-) 至少我在 JDK 中玩得很开心 :-)
  • 实际上,当我看到代码时,我 99% 以上确定会发生什么。 byte[]{0,0,-1,-1} 是 Z_SYNC_FLUSH 的标记,所以认为他可能已经击中它。
  • 我从来没有使用过GZIPInputStream,所以我不得不追踪它。我认为关键是损坏出现在预告片中而不是数据中?
  • 为什么它会停止读取而不是继续到最后并在第一次抛出异常?
  • 这个方法会阻塞直到输入数据可用,所以SOME数据在哪里,这个方法不需要返回所有数据。所以很好 imo:请参阅 gzip 本身的文档:该方法将阻塞,直到可以解压缩某些输入
猜你喜欢
  • 2016-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-17
  • 1970-01-01
  • 2013-05-04
  • 2011-09-28
  • 2017-07-23
相关资源
最近更新 更多