如何将一定数量的位写入不是 8 的倍数的文件

How to write an amount of bits to a file that is not multiple of 8

我正在编写一个 java 应用程序,它使用霍夫曼树压缩文本。
我得到的结果是一个 1 和 0 的数组。现在是 byte[].

只有我想将 8 个 1 和 0 写入一个字节,否则 "01" 将占用字符 "e".

两倍的存储空间

目前我一直在使用

byte[] output = loadedTree.encode(text);

try(ByteOutputStream boas = new ByteOutputStream()) {
    boas.write(output);
    boas.writeTo(new FileOutputStream(basePath + name));
} catch (IOException e) {
    e.printStackTrace();
}

output数组中,每个元素是一个(byte) 1或一个(byte) 0

如果我有,如何将这些数据写入文件,例如7 或 9 个数字?

将位编码为字节数组的最简单方法是通过BitSet:

private static byte[] bitsToBytes(byte[] bits) {
  BitSet bitSet = new BitSet();
  for (int i = 0; i < bits.length; i++) {
    bitSet.set(i, bits[i] == 1);
  }
  return bitSet.toByteArray();
}

注意 bits[i] == 1 而不仅仅是 bits[i],因为它是一种接受两个索引的不同方法,而不是一个索引和一个值。 您可以通过以下方式查看它:

public static void main(String[] args) {
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{0})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{1})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{1, 1})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{1, 0, 1})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{1, 1, 1, 1, 1, 1, 1})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{1, 1, 1, 1, 1, 1, 1, 0})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{1, 1, 1, 1, 1, 1, 1, 1})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{0, 0, 1, 1, 0, 0, 0, 0})));
  System.out.println(Arrays.toString(bitsToBytes(new byte[]{1, 1, 1, 1, 1, 1, 1, 1,
                                                            0, 0, 1, 1, 0, 0, 0, 0})));
}

反向转换(如评论中要求)一般需要位数,忽略尾随零位。这是代码:

private static byte[] bytesToBits(int nbits, byte[] bits) {
  BitSet bitSet = BitSet.valueOf(bits);
  byte[] result = new byte[nbits];
  for (int i = 0; i < result.length; i++) {
    result[i] = (byte) (bitSet.get(i) ? 1 : 0);
  }
  return result;
}