Convert from BitArray to Byte

95,130

Solution 1

This should work:

byte ConvertToByte(BitArray bits)
{
    if (bits.Count != 8)
    {
        throw new ArgumentException("bits");
    }
    byte[] bytes = new byte[1];
    bits.CopyTo(bytes, 0);
    return bytes[0];
}

Solution 2

A bit late post, but this works for me:

public static byte[] BitArrayToByteArray(BitArray bits)
{
    byte[] ret = new byte[(bits.Length - 1) / 8 + 1];
    bits.CopyTo(ret, 0);
    return ret;
}

Works with:

string text = "Test";
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(text);
BitArray bits = new BitArray(bytes);
bytes[] bytesBack = BitArrayToByteArray(bits);
string textBack = System.Text.Encoding.ASCII.GetString(bytesBack);
// bytes == bytesBack
// text = textBack

.

Solution 3

A poor man's solution:

protected byte ConvertToByte(BitArray bits)
{
    if (bits.Count != 8)
    {
        throw new ArgumentException("illegal number of bits");
    }

    byte b = 0;
    if (bits.Get(7)) b++;
    if (bits.Get(6)) b += 2;
    if (bits.Get(5)) b += 4;
    if (bits.Get(4)) b += 8;
    if (bits.Get(3)) b += 16;
    if (bits.Get(2)) b += 32;
    if (bits.Get(1)) b += 64;
    if (bits.Get(0)) b += 128;
    return b;
}

Solution 4

This should do the trick. However the previous answer is quite likely the better option.

    public byte ConvertToByte(BitArray bits)
    {
        if (bits.Count > 8)
            throw new ArgumentException("ConvertToByte can only work with a BitArray containing a maximum of 8 values");

        byte result = 0;

        for (byte i = 0; i < bits.Count; i++)
        {
            if (bits[i])
                result |= (byte)(1 << i);
        }

        return result;
    }

In the example you posted the resulting byte will be 0x80. In other words the first value in the BitArray coresponds to the first bit in the returned byte.

Solution 5

Unfortunately, the BitArray class is partially implemented in .Net Core class (UWP). For example BitArray class is unable to call the CopyTo() and Count() methods. I wrote this extension to fill the gap:

public static IEnumerable<byte> ToBytes(this BitArray bits, bool MSB = false)
{
    int bitCount = 7;
    int outByte = 0;

    foreach (bool bitValue in bits)
    {
        if (bitValue)
            outByte |= MSB ? 1 << bitCount : 1 << (7 - bitCount);
        if (bitCount == 0)
        {
            yield return (byte) outByte;
            bitCount = 8;
            outByte = 0;
        }
        bitCount--;
    }
    // Last partially decoded byte
    if (bitCount < 7)
        yield return (byte) outByte;
}

The method decodes the BitArray to a byte array using LSB (Less Significant Byte) logic. This is the same logic used by the BitArray class. Calling the method with the MSB parameter set on true will produce a MSB decoded byte sequence. In this case, remember that you maybe also need to reverse the final output byte collection.

Share:
95,130
Graviton
Author by

Graviton

A software developer.

Updated on July 09, 2022

Comments

  • Graviton
    Graviton almost 2 years

    I have a BitArray with the length of 8, and I need a function to convert it to a byte. How to do it?

    Specifically, I need a correct function of ConvertToByte:

    BitArray bit = new BitArray(new bool[]
    {
        false, false, false, false,
        false, false, false, true
    });
    
    //How to write ConvertToByte
    byte myByte = ConvertToByte(bit);
    var recoveredBit = new BitArray(new[] { myByte });
    Assert.AreEqual(bit, recoveredBit);
    
  • tehvan
    tehvan about 15 years
    Mind: this computes the bits in reverse order, e.g. the BitArray from the example will convert into 128, not 1!
  • Kornelije Petak
    Kornelije Petak over 14 years
    Why does this happen in a reverse order?
  • Jon Skeet
    Jon Skeet over 14 years
    @kornelijepetak: That's just the way that BitArray works, in terms of the way it chooses to copy values.
  • Admin
    Admin over 13 years
    @kornelijepetak: It is important that it copies in reverse order. If you use BitConverter on other types they are stored in little-endian format.
  • user1393201
    user1393201 over 12 years
    Instead of "bits.Length / 8", you should use "(bits.Length - 1) / 8 + 1", otherwise if the BitArray has a length of 7, your byte array will be empty. The "- 1" part makes sure a multiple of 8 will not return plus one. Thanks to stackoverflow.com/questions/17944/…
  • Tedd Hansen
    Tedd Hansen over 12 years
    Good point. A Math.Max(1, bits.Length / 8) will also work I guess (slightly more readable). I always operate on 8 bit bytes so I haven't considered the underflow condition.
  • Stephen Rudolph
    Stephen Rudolph over 9 years
    I believe there's a bug here - since count++; has already fired, the next line should be if (count == 8) {...}
  • Tim
    Tim over 9 years
    Its important to draw the distinction between byte endianness and bit endianness. Bit endianness tells you the ordering of the bits in each byte and whether the first bit is the most or least significant bit. Byte endianness tells you the expected order of the bytes in a word. Bit endianess is usually always described as "LSB first" or "MSB first" rather than little-endian or big-endian...
  • Maxence
    Maxence over 8 years
    To reverse the order: var reversed = new BitArray(bitArray.Cast<bool>().Reverse().ToArray());
  • Ark-kun
    Ark-kun over 7 years
    @TeddHansen What about 15?
  • Extragorey
    Extragorey almost 6 years
    This doesn't handle the empty case, mind - might want to add a check for when bits is empty and return an empty byte[] array accordingly.
  • Güven Acar
    Güven Acar over 5 years
    Should be "byte[(bits.Length - 1) / 8 - 1", otherwise adding unnecessary "0" byte end of byte array.
  • adyavanapalli
    adyavanapalli over 5 years
    The requirement here is that bits.Length / 8 should round up, hence it should be (int)Math.Ceiling[bits.Length / 8]. We can simply this because we know that bits.Length is a positive integer: (bits.Length + 8 - 1) / 8 == (bits.Length + 7) / 8. For bits.Length == 0, the formula conveniently returns 0.
  • Ben Jaguar Marshall
    Ben Jaguar Marshall over 5 years
    I use (bits.Length + 7) >> 3. This will always round up.
  • Caleb Vear
    Caleb Vear about 2 years
    @Tvde1 result is never left shifted. Bits that are set are individually left shifted the correct amount i and then a bitwise or is done with result. A more verbose way of writing that line is: result = result | ((byte)(1 << i)).
  • Tvde1
    Tvde1 about 2 years
    Never mind my comment :)