将位数组转换为字符串。

9

有人能帮我正确地将bittarray转换为字符串吗? 我写了这个:

static String BitArrayToStr(BitArray ba)
        {
            byte[] strArr = new byte[ba.Length / 8];

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

            for (int i = 0; i < ba.Length / 8; i++)
            {
                for (int index = i * 8, m = 1; index < i * 8 + 8; index++, m *= 2)
                {
                    strArr[i] += ba.Get(index) ? (byte)m : (byte)0;
                }
            }

            return encoding.GetString(strArr);
        }

但是在输出中我得到了这个:"���*Ȱ&����L9��q�zȲP���*Ȱ&����L9��q�zȲP���*Ȱ&Y(W�" -很多无法识别的符号,我该怎么办?

5个回答

12
您可以使用这个扩展方法:
public static string ToBitString(this BitArray bits)
{
    var sb = new StringBuilder();

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

    return sb.ToString();
}

请注意,比特位的顺序可能与您预期的相反,例如如果您想打印整数或浮点数的二进制表示。通常,最低有效位在右侧。使用上述代码,可能会出现反向情况。当然,这是一个解释问题,并取决于您具体要做什么。 - DrummerB

4

您确定输入的位数组是作为ASCII编码的字符串进行编码的吗?

使用您的代码,我进行了以下测试

string s = "Hello World";
byte[] bytes = Encoding.ASCII.GetBytes(s);
BitArray b = new BitArray(bytes);
string s2 = BitArrayToStr(b);

预期输出值为Hello World

更新:

如评论所述,ASCII编码只处理字节32-127作为可打印字符,0-32是控制字符将显示符号,而超过127的所有内容将使用ASCII回退来处理错误字节。

以下是MSDN上的一句话:

http://msdn.microsoft.com/en-us/library/system.text.decoderfallback.aspx

如果输入的字节序列无法通过编码映射,则解码操作可能失败。例如,ASCIIEncoding对象无法解码产生代码点值在U+0000到U+007F范围之外的字符的字节序列。

当不能执行编码或解码转换时,.NET Framework提供了一种称为回退的故障处理机制。您的应用程序可以使用预定义的.NET Framework编码器和解码器回退,也可以创建从EncoderFallback和EncoderFallbackBuffer类派生的自定义编码器回退或从DecoderFallback和DecoderFallbackBuffer类派生的自定义解码器回退。


问题是我在位数组中有随机值。 - ZAA
ASCII字符集仅涵盖7位字符,可打印字符位于字节范围32-127内,所有其他字符均为不可打印字符。低于32的是控制“字符”,而128-255是扩展ASCII字符,需要8位,并且所看到的符号取决于所使用的字体,或者如果您使用代码页编码,则取决于所选的代码页。因此,如果您的随机数字超出该范围,则会看到您正在看到的有趣字符。 - Chris Taylor
那么,我应该使用哪种编码来包含所有可能的二进制变体呢? - ZAA
没有任何编码能够保证每个字节组合都对应一个有效的字符。即使Unicode也有一些像代理序列这样的东西,这是由字节序列构成的字符代码点,但不是所有的字节序列都一定构成有效的代码点。你可以尝试使用各种编码,并可能提供自定义解码器回退例程来处理错误,以满足你的要求。 - Chris Taylor

0

您可以使用 此方法 将BiArray转换为字节数组:

public static byte[] ToByteArray(this BitArray bits) 
{
    int numBytes = bits.Count / 8;
    if (bits.Count % 8 != 0) numBytes++;

    byte[] bytes = new byte[numBytes];
    int byteIndex = 0, bitIndex = 0;

    for (int i = 0; i < bits.Count; i++) 
    {
        if (bits[i])
            bytes[byteIndex] |= (byte)(1 << (7 - bitIndex));

        bitIndex++;
        if (bitIndex == 8) {
            bitIndex = 0;
            byteIndex++;
        }
    }

    return bytes;
}

然后:

BitArray ba = Fill();
string result = Encoding.ASCII.GetString(ba.ToByteArray());

我尝试了这种方式,但输出仍然有很多“�”,我该如何解决? - ZAA
那么,很可能您的BitArray已经损坏或者没有进行ASCII编码。 - Darin Dimitrov
@Darin Dimitrov,楼主说得对,您需要使用不同的编码才能使其正常工作。“ASCIIEncoding对应于Windows代码页20127。因为ASCII是7位编码,所以ASCII字符仅限于最低的128个Unicode字符”[链接](http://msdn.microsoft.com/en-us/library/system.text.asciiencoding.aspx) - oleksii


0
static string BitArrayToStr(BitArray ba, bool reverseBits) {
  byte[] bytes = ((ba.Length+7)/8);
  ba.CopyTo(bytes, 0);
  if (reverseBits) ReverseBits(bytes);
  return Encoding.ASCII.GetString(bytes);
}

static void ReverseBits(byte[] bytes) {
  for(int i=0; i<bytes.Length; i++)
    bytes[i] = ReverseBits(bytes[i]);
}

static byte ReverseBits(byte b) {
  b = (byte)(((b >> 1) & 0x55) | ((b & 0x55) << 1));
  b = (byte)(((b >> 2) & 0x33) | ((b & 0x33) << 2));
  b = (byte)(((b >> 4) & 0x0F) | ((b & 0x0F) << 4));
  return b;
}

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