8

I have a string representing bits, such as:

"0000101000010000"

I want to convert it to get an array of bytes such as:

{0x0A, 0x10}

The number of bytes is variable but there will always be padding to form 8 bits per byte (so 1010 becomes 000010101).

7 Answers 7

10

Use the builtin Convert.ToByte() and read in chunks of 8 chars without reinventing the thing..

Unless this is something that should teach you about bitwise operations.

Update:


Stealing from Adam (and overusing LINQ, probably. This might be too concise and a normal loop might be better, depending on your own (and your coworker's!) preferences):

public static byte[] GetBytes(string bitString) {
    return Enumerable.Range(0, bitString.Length/8).
        Select(pos => Convert.ToByte(
            bitString.Substring(pos*8, 8),
            2)
        ).ToArray();
}
Sign up to request clarification or add additional context in comments.

3 Comments

While I'd advocate that, the only issue is that a very long bit string (though I'd have to wonder why you have that in the first place) will result in a very large number of substrings.
This is likely what i will go with. After i formulated the question, i realized that going through the string in chunks of 8 characters would be easiest. The string will likely represent 10-12 bytes so the cost in execution time is not great. Once i confirm that it all works ill give an update
Just as a site note, in my tests, the Linq example is fractionally slower than that of the loop solution provided by @AdamRobinson
2
public static byte[] GetBytes(string bitString)
{
    byte[] output = new byte[bitString.Length / 8];

    for (int i = 0; i < output.Length; i++)
    {
        for (int b = 0; b <= 7; b++)
        {
            output[i] |= (byte)((bitString[i * 8 + b] == '1' ? 1 : 0) << (7 - b));
        }
    }

    return output;
}

5 Comments

bitString.Length / 8 won't always round up. If you pass in "010" as the string, the array returned will have a length of 0.
@Tim: You're absolutely right, in fact it will always round down (integer division truncates the remainder; it doesn't round). However, the OP explicitly said that the strings would contain a full eight bits per byte.
She isn't explicit on where the padding is done, actually. I assumed the function would accept smaller strings. She may mean that the function will receive pre-padded strings. Does she want the function to silently ignore longer strings that don't make the full 8 bits? Silently disregarding data never sits right with me. If its guaranteed to be divisible by 8, it wouldn't hurt to make that clear with an assertion or exception or something. This is all kind of irrelevant navel gazing at this point, really, though. :)
@Tim: Acknowledging the navel gazing that's going on here, "...will always be padding to form 8 bits per byte (so 1010 becomes 000010101)." seems to say pretty clearly that there...will always be 8 bits per byte. ;)
The above statement from Adam is correct. I wont go into a entire explanation of the program but it is safe to assume that each byte will have a full 8 bit.
2

Here's a quick and straightforward solution (and I think it will meet all your requirements): http://vbktech.wordpress.com/2011/07/08/c-net-converting-a-string-of-bits-to-a-byte-array/

Comments

0

This should get you to your answer: How can I convert bits to bytes?

You could just convert your string into an array like that article has, and from there use the same logic to perform the conversion.

Comments

0

Get the characers in groups of eight, and parse to a byte:

string bits = "0000101000010000";

byte[] data =
  Regex.Matches(bits, ".{8}").Cast<Match>()
  .Select(m => Convert.ToByte(m.Groups[0].Value, 2))
  .ToArray();

3 Comments

Ouch. A regex just to read every N (=8) characters? Works, but seems abusive to me..
@Benjamin: Yes, it'a bit of overhead, but it's a simple way to chop up a string and it works well enough for most purposes. Having bits in a string doesn't seem like a scenario where the highest performance is required anyway...
The scenario is an odd patch to import an old file format, saved with a prototype of the program made years ago. The data must be reformatted into the new programs data structure. The files aren't that big and this feature will not be used too often, so performance is not an issue.
0
private static byte[] GetBytes(string bitString)
{
    byte[] result = Enumerable.Range(0, bitString.Length / 8).
        Select(pos => Convert.ToByte(
            bitString.Substring(pos * 8, 8),
            2)
        ).ToArray();

    List<byte> mahByteArray = new List<byte>();
    for (int i = result.Length - 1; i >= 0; i--)
    {
        mahByteArray.Add(result[i]);
    }

    return mahByteArray.ToArray();
}

private static String ToBitString(BitArray bits)
{
    var sb = new StringBuilder();

    for (int i = bits.Count - 1; i >= 0; i--)
    {
        char c = bits[i] ? '1' : '0';
        sb.Append(c);
    }

    return sb.ToString();
}

Comments

-3

You can go any of below,

        byte []bytes = System.Text.Encoding.UTF8.GetBytes("Hi");
        string str = System.Text.Encoding.UTF8.GetString(bytes);


        byte []bytesNew = System.Convert.FromBase64String ("Hello!");
        string strNew = System.Convert.ToBase64String(bytesNew);

2 Comments

The question was about converting a string representing bits to an array of bytes representing the value of those bits. Your solution doesn't answer that question.
Thank you for sharing this - as this is exactly what I was looking for. Many of us search through these threads, looking for solutions that might not match 100% to the initial question, but contain useful ideas.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.