【问题标题】:How to tackle byte stuffing in Java?如何解决 Java 中的字节填充问题?
【发布时间】:2012-11-06 14:32:40
【问题描述】:

我正在读取 Java 中的二进制文件,该文件在保存时是字节填充的,因此读取时必须反转操作。填充在于在FF 字节之后添加一个额外的零字节。读取时必须丢弃该零字节。我正在使用DataInputStream 来读取文件,尽管这不应该有太大的区别,看看我是如何只对程序的那一部分使用“原始”读取到数组函数的。

无论如何,这就是我目前所得到的:

public static byte[] unstuff(byte[] stuffed) {
    int bytesToSkip = 0;
    for(int i=0;i<stuffed.length - 1;++i) {
        if(stuffed[i] == 0xFF && stuffed[i+1] == 0) {
            ++bytesToSkip;
        }
    }
    if(bytesToSkip == 0) return stuffed;

    byte unstuffed[] = new byte[stuffed.length - bytesToSkip];
    int j=0;
    for(int i=0;i<stuffed.length - 1;++i) {
        if(stuffed[i] == 0xFF && stuffed[i+1] == 0) {
            ++i;
            continue;
        }
        else {
            unstuffed[j] = stuffed[i];
            ++j;
        }
    }
    return unstuffed;
}

基本上,该函数计算要跳过的字节数,然后分配一个比原始填充数组短该字节数的数组,然后复制它们,跳过不需要的零字节。

问题是:有没有其他方法可以做到这一点,或许更流畅、更高效、更直接?将字节放在另一个容器中然后删除它们而不是复制整个数组会更好吗?

【问题讨论】:

  • 在扫描数组时写入 byteArrayOutputStream,扫描输入数组后,使用toByteArray() 方法将 ByteArayOutputStream 转换为字节数组。 Incidenta;;y 为什么for(int i=0;i&lt;stuffed.length - 1;++i) {你;在这里跳过最后一个字符。考虑一个包含 3 个元素的数组。它的长度为 3,索引为 0、1 和 2,因此您希望在 i &lt; array.length 时继续,而不是 i&lt; length-1,因为这只会为 i = 0 和 i=1 提供 2 次迭代。
  • @SteveAtkinson 您的问题的答案在于stuffed[i+1]
  • 假设数组总是以 FF 00 序列结尾,但没有说明 ;)
  • @SteveAtkinson 不,除了倒数第二个字节不是ff 的数组不以ff 00 结尾这一显而易见的事实之外,它不会假设任何事情。

标签: java io binaryfiles


【解决方案1】:

您可以将其作为 InputStream 本身的包装器:

new DataInputStream(new FilterInputStream(stream)) {
  int buf = -1;

  public int read() {
    if (buf != -1) {
      int result = buf;
      buf = -1;
      return result;
    } else {
      int b = super.read();
      if (b == 0xFF) {
        super.skip(1); // skip the 0 byte
      }
      return b;
    }
  }

  public int read(byte[] bytes, int off, int len) {
    int dst = 0;
    while (dst == 0) {
      int readBytes = super.read(bytes, off, len);
      if (readBytes == -1) return -1;
      int dst = 0;
      for (int i = 0; i < readBytes; i++) {
        bytes[off + dst] = bytes[off + i];
        if (bytes[off + i] == (byte) 0xFF) {
          i++; // skip the 0 byte afterwards
        }
      }
    }
    return dst;
  }
}

【讨论】:

    【解决方案2】:

    最佳方法是使用原始数组进行FF 00 压缩。只要满足条件,就不要增加目标索引。完成后,数组将包含您想要的序列,但它可能太大,最后有额外的字节。然后你要么复制到一个较短的数组,要么按原样使用原始数组,但将它传递给接受偏移量+计数的方法,传递较低的字节数。

    int target = 0;
    for (int i = 1; i < stuffed.length; ++i) {
        if (stuffed[i-1] == 0xFF && stuffed[i] == 0) continue;
        if (i != target) stuffed[target++] = stuffed[i];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      • 2010-11-28
      • 2020-06-28
      相关资源
      最近更新 更多