4
votes

I'm trying to convert a byte array to a BitSet. The following is the code I'm using:

public BitSet byteToBits(byte[] bytearray){
    BitSet returnValue = new BitSet(bytearray.length*8);
    ByteBuffer  byteBuffer = ByteBuffer.wrap(bytearray);
    //System.out.println(byteBuffer.asIntBuffer().get(1));
    //Hexadecimal values used are Big-Endian, because Java is Big-Endian
    for (int i = 0; i < bytearray.length; i++) {
        byte thebyte = byteBuffer.get(i);
        for (int j = 0; j <8 ; j++) {
            returnValue.set(i*8+j,isBitSet(thebyte,j));
        }
    }
    return returnValue;
}

private static Boolean isBitSet(byte b, int bit)
{
    return (b & (1 << bit)) != 0;
}

I'm testing it with a JUnit test, shown below.

@org.junit.Test
public void byteToBits() throws Exception {
    byte[] input = new byte[]{(byte) 0b1011_1011};
    BitSet expectedOutput = new BitSet(8);
    expectedOutput = BitSet.valueOf(new byte[]{(byte)0b1011_1011});
    assertEquals(expectedOutput,converter.byteToBits(input));
    assertEquals(expectedOutput.toByteArray(),input);
}

@Test
public void testBytestoBitslength() throws Exception {
    byte[] input = new byte[]{(byte) 0xFFFF,(byte)0x7F70,(byte)0xF45A,(byte)0xA24B};
    BitSet output = converter.byteToBits(input);
    System.out.println("byte[] length: "+input.length+ "x8: "+input.length*8);
    System.out.println("BitSet length: "+output.length());
    System.out.println(input.toString());
    System.out.println(output.toByteArray().toString());
    assertTrue(output.length()==input.length*8);
}

This code fails the test though, and I have no idea why.

For byteToBits:

java.lang.AssertionError: 
Expected :[B@6438a396
Actual   :[B@e2144e4

For testBytestoBitslength:

byte[] length: 4x8: 32
BitSet length: 31
[B@4f2410ac
[B@722c41f4

Tried replacing it with a BitSet.valueOf(byte[]) method call. It still fails, albeit more interestingly.

@Test
public void curiosity() throws Exception {
    byte[] byteArray = new byte[]{1, 2, 3};
    BitSet bitSet = BitSet.valueOf(byteArray);
    System.out.println("byte[]: "+byteArray);
    System.out.println(bitSet.toByteArray());
    assertEquals(ByteBuffer.wrap(byteArray),ByteBuffer.wrap(bitSet.toByteArray()));
    assertEquals(bitSet.length(),byteArray.length*8);
}

This returns the following:

byte[]: [B@6438a396
BitSet: [B@e2144e4

java.lang.AssertionError: 
Expected :18
Actual   :24

When wrapped by a ByteBuffer, the two objects return the same thing, but they appear to be completely different, and the two objects have different lengths.

2
Have you tried replacing assertEquals(expectedOutput.toByteArray(),input); with assertEquals(ByteBuffer.wrap(expectedOutput.toByteArray()), ByteBuffer.wrap(input));? - Paul Boddington
@PaulBoddington Wrapping the byte[]s in a ByteBuffer fixed the AssertionError for the byteToBits method. Why did it fix the error? - user1
Because byte[] does not override equals. equals for byte[] simply tests if they are exactly the same instance. You want to test if they have the same length and the same elements. The only ways to do this is Arrays.equals or to wrap them in ByteBuffers and check the ByteBuffers are equal. - Paul Boddington
Try System.out.println(new byte[]{1, 2, 3}.equals(new byte[]{1, 2, 3}));. It actually prints false. - Paul Boddington
Is there any way to fix the length error, or is that a different problem? - user1

2 Answers

10
votes

For converting byte to BitSet you should try

final byte b = ...;
final BitSet set = BitSet.valueOf(new byte[] { b });

You can refer to Convert a byte or int to bitset it might help you.

0
votes

One cannot compare two byte[] arrays directly, as byte[]s dont implement comparable. The solution here would be to wrap them in a ByteBuffer, as suggested by @PaulBoddington.

assertEquals(ByteBuffer.wrap(expectedOutput.toByteArray()),ByteBuffer.wrap(input));

The other length issue is caused by BitSet itself. BitSet.length() returns the length from index 0 to the last set bit in the BitSet, which would cause the discrepancy in the length of the BitSet.length() vs the byte[].length*8. The only solution here would be to use BitSet.toByteArray().length*8, where ever there is a need for BitSet.length().