Java BitSet和byte []用法

gmn*_*nnn 11 java bytearray bitset

我有这个应用程序,我应该BitSet大量使用类,并逐位写入文件.我知道我不能将位写入文件,所以首先我将BitSet对象转换为字节数组并写为字节数组.但问题是,因为BitSet类索引right to left,当我将BitSet对象转换为字节数组并写入文件时,它会向后写入.

例如,这是我的BitSet对象:

10100100
Run Code Online (Sandbox Code Playgroud)

和BitSet.get(0)给出false,BitSet.get(7)给出true.我想把它写成文件,如:

00100101
Run Code Online (Sandbox Code Playgroud)

所以第一位为0,最后一位为1.

我的转换方法:

public static byte[] toByteArray(BitSet bits) 
{
    byte[] bytes = new byte[(bits.length() + 7) / 8];       
    for (int i = 0; i < bits.length(); i++) {
        if (bits.get(i)) {
            bytes[bytes.length - i / 8 - 1] |= 1 << (i % 8);
        }
    }
    return bytes;
}
Run Code Online (Sandbox Code Playgroud)

我的写法:

    FileOutputStream fos = new FileOutputStream(filePath);
    fos.write(BitOperations.toByteArray(cBitSet));
    fos.close();
Run Code Online (Sandbox Code Playgroud)

这是打算像这样还是我做错了什么?谢谢.

fge*_*fge 6

BitSet 有几个问题:

  • 它在输出上提供的字节数组的长度.toByteArray()取决于最高位设置为1(如果没有设置则为0,如果最后一位设置为<1则为1,如果<16则为2等 - 本质上是indexOf(highestBitSet) + 7) / 8);
  • 因此,你不能依赖它来计算固定长度的位掩码.

考虑使用包装器ByteBuffer代替.示例代码如下.

注意:这使用"静态工厂方法"进行构造,因此您需要使用BitFlags.withByteLength()BitFlags.withBitLength()创建新实例.当然,您可以为此设计自己的方法,或者只是将构造函数设为公共.要获取底层数组,请调用.toByteArray().

public final class BitFlags
{
    private final int nrBytes;
    private final ByteBuffer buf;

    private BitFlags(final int nrBytes)
    {
        if (nrBytes < 1)
            throw new IllegalArgumentException("need at least one byte");
        this.nrBytes = nrBytes;
        buf = ByteBuffer.allocate(nrBytes);
    }

    public static BitFlags withByteLength(final int nrBytes)
    {
        return new BitFlags(nrBytes);
    }

    public static BitFlags withBitLength(final int nrBits)
    {
        return new BitFlags((nrBits - 1) / 8 + 1);
    }

    public void setBit(final int bitOffset)
    {
        if (bitOffset < 0)
            throw new IllegalArgumentException();

        final int byteToSet = bitOffset / 8;
        if (byteToSet > nrBytes)
            throw new IllegalArgumentException();

        final int offset = bitOffset % 8;
        byte b = buf.get(byteToSet);
        b |= 1 << offset;
        buf.put(byteToSet, b);
    }

    public void unsetBit(final int bitOffset)
    {
        if (bitOffset < 0)
            throw new IllegalArgumentException();

        final int byteToSet = bitOffset / 8;
        if (byteToSet > nrBytes)
            throw new IllegalArgumentException();

        final int offset = bitOffset % 8;
        byte b = buf.get(byteToSet);
        b &= ~(1 << offset);
        buf.put(byteToSet, b);
    }

    public byte[] toByteArray()
    {
        return buf.array();
    }
}
Run Code Online (Sandbox Code Playgroud)


Pat*_*han 6

BitSet实现Serializable.如果您只需要能够在Java中恢复BitSet,并且不需要在文件中检查其状态,您应该告诉它将自己保存到文件中.

如果要将其写入包含其他非序列化数据的文件,可以将其写入ByteArrayOutputStream并从中检索byte [].但是,直接写入文件可能会获得更好的性能.