如何在Java中处理字节填充?

时间:2012-11-18 13:51:04

标签: java io binaryfiles

我正在读取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;
}

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

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分: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;
  }
}