0

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

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

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;
}

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

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

4

2 回答 2

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;
  }
}
于 2012-11-18T16:08:42.960 回答
1

最优化的方法是使用原始数组进行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];
}
于 2012-11-18T14:18:37.370 回答