35

How do you convert a string such as "01110100011001010111001101110100" to a byte array then used File.WriteAllBytes such that the exact binary string is the binary of the file. In this case it would be the the text "test".

1

5 Answers 5

48

In case you don't have this LINQ fetish, so common lately, you can try the normal way

string input ....
int numOfBytes = input.Length / 8;
byte[] bytes = new byte[numOfBytes];
for(int i = 0; i < numOfBytes; ++i)
{
    bytes[i] = Convert.ToByte(input.Substring(8 * i, 8), 2);
}
File.WriteAllBytes(fileName, bytes);

LINQ is great but there must be some limits.

Sign up to request clarification or add additional context in comments.

4 Comments

This assumes that the string length is a multiple of 8... But you're right, it is probably easier to understand that way. I guess I'm totally addicted to LINQ ;)
Hmm. I'd argue that the LINQ is more understandable. It describes concisely what is being done without describing the (noisy) steps to acheive that goal. It has a much higher content to noise ratio.
@spender Sure LINQ is a nice tool for uses it was meant for, but for this simple and straightforward case? Come on, Thomas's code is longer, creates at least 4 enumerable objects, one intermediate array of strings, 5 delegates, and an anonymous reference type for every digit '0' or '1'. This is insane.
if input.Length / 8 is not properly rounded, if the double value is 1.75, numOfBytes is 1. Beware of that!
12

You could start by splitting the string into a sequence of 8-character strings, then convert those strings to bytes, and eventually write the bytes to a file

string input = "01110100011001010111001101110100";
var bytesAsStrings =
    input.Select((c, i) => new { Char = c, Index = i })
         .GroupBy(x => x.Index / 8)
         .Select(g => new string(g.Select(x => x.Char).ToArray()));
byte[] bytes = bytesAsStrings.Select(s => Convert.ToByte(s, 2)).ToArray();
File.WriteAllBytes(fileName, bytes);

EDIT: here's another way to split the string into 8-character chunks, perhaps a bit simpler :

int nBytes = (int)Math.Ceiling(input.Length / 8m);
var bytesAsStrings =
    Enumerable.Range(0, nBytes)
              .Select(i => input.Substring(8 * i, Math.Min(8, input.Length - 8 * i)));

If you know that the length of the string is a multiple of 8, you can make it even simpler :

int nBytes = input.Length / 8;
var bytesAsStrings =
    Enumerable.Range(0, nBytes)
              .Select(i => input.Substring(8 * i, 8));

1 Comment

Just bumped into this question. A nice toy problem... good for an interview. I thought I'd give it a shot before reading the answers. Matched your second approach virtually term for term. I too am addicted to LINQ! +1
4

A bit late, but here's my 2 cents:

var binaryStr = "01110100011001010111001101110100";

var byteArray = Enumerable.Range(0, int.MaxValue/8)
                          .Select(i => i*8)
                          .TakeWhile(i => i < binaryStr.Length)
                          .Select(i => binaryStr.Substring(i, 8))
                          .Select(s => Convert.ToByte(s, 2))
                          .ToArray();
File.WriteAllBytes("C:\temp\test.txt", byteArray);

Comments

4

Actually the answer by @Maciej is not correct. As @Phate01 noticed the numOfBytes is correct only for input length which is a power of 8. The second thing is that the byte array should be populated from n to 0 index not the opposite way. Here's the code example:

var bits = "000011110000001000";
var numOfBytes = (int)Math.Ceiling(bits.Length / 8m);
var bytes = new byte[numOfBytes];
var chunkSize = 8;

for (int i = 1; i <= numOfBytes; i++)
{
    var startIndex = bits.Length - 8 * i;
    if (startIndex < 0)
    {
        chunkSize = 8 + startIndex;
        startIndex = 0;
    }
    bytes[numOfBytes - i] = Convert.ToByte(bits.Substring(startIndex, chunkSize), 2);
}

This can be improved to get rid of the if statetment but in this form it's more understandable.

Comments

1

The other answers have you covered, but just for fun I wrote the opposite. Going from the string to the ascii binary representation:

    private static string StringToAsciiBin(string s)
    {
        string output = "";
        foreach (char c in s.ToCharArray())
        {
            for (int i = 128; i >= 1; i /=2)
            {
                if (((int)c & i) > 0)
                {
                    output += "1";
                }
                else
                {
                    output += "0";
                }
            }
        }
        return output;
    }

2 Comments

You would want to go from a byte array to the binary represenation. A char is a 16 bit data type, so you would chop off the top eight bits of each character code. Also, don't use += to build a string, it scales terribly badly, use a StringBuilder instead.
@Guffa Agreed on using StringBuilder, but if you have "01110100011001010111001101110100" as an input, sorry, that's a string, not a byte[], until you separate it out into blocks of 8.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.