[英]Java BitSet and byte[] usage
我有這個應用程序,我應該大量使用BitSet
類並逐位寫入文件。 我知道我不能將位寫入文件,所以首先我將BitSet
對象轉換為字節數組並寫為字節數組。 但問題是,由於BitSet
類right to left
索引,當我將BitSet
對象轉換為字節數組並寫入文件時,它向后寫入。
例如,這是我的BitSet對象:
10100100
和BitSet.get(0)給出false,BitSet.get(7)給出true。 我想把它寫成文件,如:
00100101
所以第一位為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;
}
我的寫法:
FileOutputStream fos = new FileOutputStream(filePath);
fos.write(BitOperations.toByteArray(cBitSet));
fos.close();
這是打算像這樣還是我做錯了什么? 謝謝。
BitSet
有幾個問題:
.toByteArray()
,取決於設置為1的最高位(如果沒有設置,則為0;如果最后一位設置為<8,則為1,如果<16等,則為1等)本質, 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();
}
}
BitSet實現Serializable。 如果您只需要能夠在Java中恢復BitSet,並且不需要在文件中檢查其狀態,您應該告訴它將自己保存到文件中。
如果要將其寫入包含其他非序列化數據的文件,可以將其寫入ByteArrayOutputStream並從中檢索byte []。 但是,直接寫入文件可能會獲得更好的性能。
這看起來很合理。 它不會很快,但它應該工作。 如果您希望它以相反的順序寫出位,只需反轉索引和移位:
byte[] bytes = new byte[(bits.length() + 7) / 8];
for (int i = 0; i < bits.length(); i++) {
if (bits.get(i)) {
bytes[i / 8] |= 1 << (7 - i % 8);
}
}
甚至:
bytes[i / 8] |= 128 >> (i % 8);
如果你的bitset相當稀疏(或者即使它不是),只能迭代1位可能更有效:
byte[] bytes = new byte[(bits.length() + 7) / 8];
for ( int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1) ) {
bytes[i / 8] |= 128 >> (i % 8);
}
如果密集位集需要更高的速度, 可以嘗試使用標准的BitSet.toByteArray()
方法,然后使用bit-twiddling技巧來反轉各個字節中的位:
byte[] bytes = bits.toByteArray();
for ( int i = 0; i < bytes.length; i++ ) {
byte b = bytes[i];
b = ((b & 0x0F) << 4) | ((b & 0xF0) >> 4);
b = ((b & 0x33) << 2) | ((b & 0xCC) >> 2);
b = ((b & 0x55) << 1) | ((b & 0xAA) >> 1);
bytes[i] = b;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.