How can i iterate bits in a byte array?
-
You can't. At least not directly. What are you trying to do, perhaps there is a better way. A byte array holds a collection of bytes.OscarRyz– OscarRyz2009-06-23 19:03:41 +00:00Commented Jun 23, 2009 at 19:03
-
20And once again, I wish that java.util.BitSet had a byte[] constructor.Michael Myers– Michael Myers ♦2009-06-23 19:05:21 +00:00Commented Jun 23, 2009 at 19:05
-
It can be done. I'd vote you go with Jon Skeet's method. However, in most cases when working with bits, there are some fancy bitwise operators that can make your task go much faster. If you tell us what you're trying to do, exactly, we might help you find a better way than iterating the bits.StriplingWarrior– StriplingWarrior2009-06-23 19:31:31 +00:00Commented Jun 23, 2009 at 19:31
-
I am trying to interpret the bitfield message of bittorrent protocol each bit represents a a piece's availability. i need to iterate and determine which peer has which pieces available.Hamza Yerlikaya– Hamza Yerlikaya2009-06-23 20:33:35 +00:00Commented Jun 23, 2009 at 20:33
8 Answers
You'd have to write your own implementation of Iterable<Boolean> which took an array of bytes, and then created Iterator<Boolean> values which remembered the current index into the byte array and the current index within the current byte. Then a utility method like this would come in handy:
private static Boolean isBitSet(byte b, int bit)
{
return (b & (1 << bit)) != 0;
}
(where bit ranges from 0 to 7). Each time next() was called you'd have to increment your bit index within the current byte, and increment the byte index within byte array if you reached "the 9th bit".
It's not really hard - but a bit of a pain. Let me know if you'd like a sample implementation...
Comments
public class ByteArrayBitIterable implements Iterable<Boolean> {
private final byte[] array;
public ByteArrayBitIterable(byte[] array) {
this.array = array;
}
public Iterator<Boolean> iterator() {
return new Iterator<Boolean>() {
private int bitIndex = 0;
private int arrayIndex = 0;
public boolean hasNext() {
return (arrayIndex < array.length) && (bitIndex < 8);
}
public Boolean next() {
Boolean val = (array[arrayIndex] >> (7 - bitIndex) & 1) == 1;
bitIndex++;
if (bitIndex == 8) {
bitIndex = 0;
arrayIndex++;
}
return val;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] a) {
ByteArrayBitIterable test = new ByteArrayBitIterable(
new byte[]{(byte)0xAA, (byte)0xAA});
for (boolean b : test)
System.out.println(b);
}
}
Comments
Original:
for (int i = 0; i < byteArray.Length; i++)
{
byte b = byteArray[i];
byte mask = 0x01;
for (int j = 0; j < 8; j++)
{
bool value = b & mask;
mask << 1;
}
}
Or using Java idioms
for (byte b : byteArray ) {
for ( int mask = 0x01; mask != 0x100; mask <<= 1 ) {
boolean value = ( b & mask ) != 0;
}
}
2 Comments
An alternative would be to use a BitInputStream like the one you can find here and write code like this:
BitInputStream bin = new BitInputStream(new ByteArrayInputStream(bytes));
while(true){
int bit = bin.readBit();
// do something
}
bin.close();
(Note: Code doesn't contain EOFException or IOException handling for brevity.)
But I'd go with Jon Skeets variant and do it on my own.
Comments
I needed some bit streaming in my application. Here you can find my BitArray implementation. It is not a real iterator pattern but you can ask for 1-32 bits from the array in a streaming way. There is also an alternate implementation called BitReader later in the file.
Comments
I know, probably not the "coolest" way to do it, but you can extract each bit with the following code.
int n = 156;
String bin = Integer.toBinaryString(n);
System.out.println(bin);
char arr[] = bin.toCharArray();
for(int i = 0; i < arr.length; ++i) {
System.out.println("Bit number " + (i + 1) + " = " + arr[i]);
}
10011100
Bit number 1 = 1
Bit number 2 = 0
Bit number 3 = 0
Bit number 4 = 1
Bit number 5 = 1
Bit number 6 = 1
Bit number 7 = 0
Bit number 8 = 0
3 Comments
In addition to the approaches shown in the other answers, you can use BitSet for this:
byte[] bytes = ...;
BitSet bitSet = BitSet.valueOf(bytes);
for(int i = 0; i < bitSet.length(); i++){
boolean bit = bitSet.get(i);
//use your bit
}
BitSet.valueOf was introduced in Java 7.