【问题标题】:inflater does not decompress all the compressed bytesinflater 不会解压缩所有压缩字节
【发布时间】:2016-03-09 11:14:55
【问题描述】:

Deflater 压缩一个由 0 到 99 字节组成的字节数组(长度为 100) 压缩的字节数组作为解压缩的输入传递给 Inflater。 解压器返回的长度在原始列表中缺少 3 个字节。

以下是代码:

        byte orig[] = new byte[100];
        IntStream.range(0, 100).forEach(i -> orig[i] = (byte) i);


        System.out.println("OrigLength: " + orig.length);

        byte[] compressed = new byte[orig.length];


        Deflater deflater = new Deflater();
        deflater.setInput(orig);
        deflater.finish();
        int compressedLength = deflater.deflate(compressed);
        deflater.end();
        System.out.println("--------------------------------------------------------------------");
        System.out.println("CompressedLength::" + compressedLength);
        for (int i = 0; i < compressedLength; i++) {
            System.out.print(compressed[i] + " ");
        }


        Inflater decompresser = new Inflater();
        decompresser.setInput(compressed, 0, compressedLength);
        byte[] result = new byte[compressedLength];
        int resultLength = decompresser.inflate(result);
        decompresser.end();

        System.out.println("\n--------------------------------------------------------------------");
        System.out.println("DecompressedLength::" + resultLength);
        for (int i = 0; i < resultLength; i++) {
            System.out.print(result[i] + " ");
        }

        System.out.println("\n--------------------------------------------------------------------");

输出:

原始长度:100


压缩长度::100

120 -100 99 96 100 98 102 97 101 99 -25 -32 -28 -30 -26 -31 -27 -29 23 16 20 18 22 17 21 19 -105 -112 -108 -110 -106 -111 -107 -109 87 80 84 82 86 81 85 83 -41 -48 -44 -46 -42 -47 -43 -45 55 48 52 50 54 49 53 51 -73 -80 -76 -78 -74 -79 -75 -77 119 112 116 114 118 113 117 115 -9 -16 -12 -14 > -10 -15 -11 -13 15 8 12 10 14 9 13 11 - 113 -120 -116 -118 -114 -119 -115 -117 79 72


解压长度::97

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96


进程以退出代码 0 结束

解压后长度为 97,原始长度为 100。请问我的代码有什么问题吗?

谢谢。

【问题讨论】:

    标签: java zip compression


    【解决方案1】:

    虽然不清楚但我找到了以下,

    有问题的不是充气机而是放气机。

    Deflater 压缩数据时我惊讶地注意到字节数比原始未压缩数据增加了。例如上面的压缩数据数组有 100 个元素,因为数组是用大小 100 构造的。

    但是,如果我将压缩数组的大小任意增加为 200,然后使用该数组,则 deflate 方法将返回值 108(此处比原始 100 多 8 个字节)。这让我感到困惑,因为要了解我需要知道究竟什么是放气压缩以及我正在经历的算法是如何工作的。

    所以这里是更新的代码,

    byte orig[] = new byte[100];
    
            IntStream.range(0, 100).forEach(i -> orig[i] = (byte) i);
    
            System.out.println("OrigLength: " + orig.length);
    
            byte[] compressed = new byte[orig.length * 2]; // double it arbitrarily chosen 
    
    
            Deflater deflater = new Deflater();
            deflater.setInput(orig);
            deflater.finish();
            int compressedLength = 0;
            compressedLength = deflater.deflate(compressed);
            deflater.end();
            System.out.println("--------------------------------------------------------------------");
            System.out.println("CompressedLength::" + compressedLength); //now this will be 108
            for (int i = 0; i < compressedLength; i++) {
                System.out.print(compressed[i] + " ");
            }
    
    
            Inflater decompresser = new Inflater();
            byte[] result = new byte[orig.length];
            decompresser.setInput(compressed, 0, compressedLength);
            int resultLength  = decompresser.inflate(result);
            decompresser.end();
    
            System.out.println("\n--------------------------------------------------------------------");
            System.out.println("DecompressedLength::" + resultLength);
            for (int i = 0; i < resultLength; i++) {
                System.out.print(result[i] + " ");
            }
    
            System.out.println("\n--------------------------------------------------------------------");
    

    输出:

    原始长度:100


    CompressedLength::108 // 这是关注点,额外增加 8 个字节

    120 -100 99 96 100 98 102 97 101 99 -25 -32 -28 -30 -26 -31 -27 -29 23 16 20 18 22 17 21 19 -105 -112 -108 -110 -106 -111 -107 -109 87 80 84 82 86 81 85 83 -41 -48 -44 -46 -42 -47 -43 -45 55 48 52 50 54 49 53 51 -73 -80 -76 -78 -74 -79 -75 -77 119 112 116 114 118 113 117 115 -9 -16 -12 -14 -10 -15 -11 -13 15 8 12 10 14 9 13 11 -113 -120 -116 -118 -114 -119 -115 -117 79 72 76 74 6 0 -117 124 19 87

    解压长度::100

    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 454 42 43 43 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

    【讨论】:

      【解决方案2】:

      你得看看这个例子:

      https://github.com/DawnScience/dawn-common/blob/master/org.dawb.common.util/src/org/dawb/common/util/list/PrimitiveArrayEncoder.java#L95

      public static String compress(final String expanded) {
      
          try {
              byte[] input = expanded.getBytes("US-ASCII");
      
              // Compress the bytes
              byte[] output = new byte[input.length];
              Deflater compresser = new Deflater();
              compresser.setInput(input);
              compresser.finish();
              final int size  = compresser.deflate(output);
      
              return new String(output, 0, size, "US-ASCII");
          } catch (Exception ne) {
              ne.printStackTrace();
              return null;
          }
      }
      
      /**
       * Inflate a string
       * @param compressed
       * @return Inflated string.
       */
      public static String expand(final String compressed) {
      
          try {
              final byte[] output = compressed.getBytes("US-ASCII");
      
              // Decompress the bytes
              Inflater decompresser = new Inflater();
              decompresser.setInput(output, 0, output.length);
      
              byte[] result = new byte[output.length*2];
              int resultLength = decompresser.inflate(result);
              decompresser.end();
      
              // Decode the bytes into a String
              return new String(result, 0, resultLength, "US-ASCII");
      
          } catch (Exception ne) {
              ne.printStackTrace();
              return null;
          }
      
      }
      

      【讨论】:

      • 好吧,我使用纯字节而不是将字符串转换为字节。我想知道我的代码有什么问题,inflater 没有返回最初压缩的所有字节。
      【解决方案3】:

      您可能会在这里找到一些想法:

      private static byte[] readCompressed(final Repository db,
              final AnyObjectId id) throws FileNotFoundException, IOException {
          final FileInputStream objStream = new FileInputStream(db.toFile(id));
          final byte[] compressed;
          try {
              compressed = new byte[objStream.available()];
              int off = 0;
              while (off < compressed.length)
                  off += objStream.read(compressed, off, compressed.length - off);
          } finally {
              objStream.close();
          }
          return compressed;
      }
      

      完整代码在这里: http://code.openhub.net/file?fid=50oAEc5CLFonr_2GPq0IoqxVPw8&cid=6SVb15jezXE&s=inflater%20does%20not%20decompress%20all%20the%20compressed%20bytes&pp=0&fl=Java&ff=1&projSelected=false&filterChecked,=true&mp,=1&filterChecked=true&mp=1&ml=1&me=1&md=1#L26

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-06
        • 1970-01-01
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-11
        相关资源
        最近更新 更多