tags:

views:

114

answers:

4

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".

+6  A: 

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));
Thomas Levesque
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
spender
A: 

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;
    }
jwsample
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
+3  A: 

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.

Maciej Hehl
Much more understandable
jwsample
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 ;)
Thomas Levesque
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
@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.
Maciej Hehl
A: 

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);
theburningmonk