这是Java GZipInputStream类中的错误吗?

Jac*_*cob 10 java gzip gzipinputstream

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

在考虑提交错误报告之前,我想看看社区在这里想到了什么.

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

这是来源:

  @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();
    }
  }
Run Code Online (Sandbox Code Playgroud)

bes*_*sss 9

决定进行测试:

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

接下来read()抛出"Corrupt GZIP预告片".

所以这一切都很好!(并且没有错误,至少在GZIPInputStream中)

  • *此方法阻塞直到输入数据可用*,因此在某些数据中,该方法不需要返回所有数据.所以它很好imo:看看gzip本身的文档:*该方法将阻塞,直到某些输入可以解压缩* (2认同)