将二进制字符串表示转换为字节数组。

35

如何将字符串“01110100011001010111001101110100”转换为字节数组,然后使用File.WriteAllBytes,并使得文件的二进制内容与原始字符串相同。在这种情况下,它将是文本“test”的二进制表示。


1
这是一个很好的起点:http://msdn.microsoft.com/zh-cn/library/system.convert_methods.aspx - NullUserException
5个回答

48

如果你不喜欢这种最近流行的 LINQ 热潮,你可以尝试正常的方式。

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很棒,但一定有一些限制。


5
假设字符串长度是8的倍数......但你说得对,那样可能更容易理解。我想我完全沉迷于LINQ中了 ;) - Thomas Levesque
2
嗯,我认为LINQ更易于理解。它简洁地描述了正在进行的操作,而不描述实现该目标的(嘈杂)步骤。它具有更高的内容噪声比。 - spender
3
@spender,确实LINQ对于它所设计的用途非常好,但对于这个简单明了的情况来说呢?拜托,Thomas的代码更长,至少创建了4个可枚举对象、一个字符串中间数组、5个委托,以及'0'或'1'每个数字都会创建一个匿名引用类型。这太疯狂了。 - Maciej Hehl
4
如果 input.Length / 8 没有被正确地四舍五入,且 double 值为 1.75,则 numOfBytes 为 1。请注意! - Phate01

12
你可以先将字符串分割成8个字符一组的序列,然后将这些字符串转换为字节,最后将这些字节写入文件。
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);

编辑:这里有另一种将字符串分成8个字符块的方法,可能更简单:

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

如果你知道字符串的长度是8的倍数,你可以将它变得更简单:

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

刚碰到这个问题。一个不错的玩具问题... 适合面试。在阅读答案之前,我想尝试一下。几乎逐字逐句地匹配了你的第二个方法。我也沉迷于LINQ!+1 - spender

4

实际上,@Maciej的答案是不正确的。正如@Phate01所指出的,numOfBytes只对长度为8的幂次的输入有效。第二件事是字节数组应该从n0的索引填充,而不是相反的方式。以下是代码示例:

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

这可以改进以消除if语句,但在这种形式下更易理解。


4
有点晚了,但这是我的两分钱意见:
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);

1
其他答案已经回答了你的问题,但是为了好玩,我写了相反的方法。从字符串转换为ASCII二进制表示:
    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
你需要将字节数组转换为二进制表示。char是一个16位数据类型,因此您需要截掉每个字符代码的前8位。另外,不要使用+=来构建字符串,它的性能非常糟糕,请改用StringBuilder。 - Guffa
@Guffa同意使用StringBuilder,但是如果您的输入是"01110100011001010111001101110100",那么抱歉,这是一个字符串,而不是byte[],除非您将其分成8个块。 - vapcguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接