【问题标题】:Convert from BitArray to Byte从位数组转换为字节
【发布时间】:2010-10-08 06:57:15
【问题描述】:

我有一个长度为 8 的 BitArray,我需要一个函数将其转换为 byte。怎么做?

具体来说,我需要ConvertToByte的正确函数:

BitArray bit = new BitArray(new bool[]
{
    false, false, false, false,
    false, false, false, true
});

//How to write ConvertToByte
byte myByte = ConvertToByte(bit);
var recoveredBit = new BitArray(new[] { myByte });
Assert.AreEqual(bit, recoveredBit);

【问题讨论】:

    标签: c# .net binary bitarray base-class-library


    【解决方案1】:

    这应该可行:

    byte ConvertToByte(BitArray bits)
    {
        if (bits.Count != 8)
        {
            throw new ArgumentException("bits");
        }
        byte[] bytes = new byte[1];
        bits.CopyTo(bytes, 0);
        return bytes[0];
    }
    

    【讨论】:

    • Mind:这会以相反的顺序计算位,例如示例中的 BitArray 将转换为 128,而不是 1!
    • @kornelijepetak:就选择复制值的方式而言,这正是 BitArray 的工作方式。
    • @kornelijepetak:重要的是它以相反的顺序复制。如果您在其他类型上使用 BitConverter,它们会以 little-endian 格式存储。
    • 区分字节字节序和位字节序很重要。位字节序告诉您每个字节中位的顺序以及第一位是最高有效位还是最低有效位。字节字节序告诉您一个字中字节的预期顺序。位字节序通常总是被描述为“LSB first”或“MSB first”,而不是 little-endian 或 big-endian...
    • 反转顺序:var reversed = new BitArray(bitArray.Cast<bool>().Reverse().ToArray());
    【解决方案2】:

    有点晚了,但这对我有用:

    public static byte[] BitArrayToByteArray(BitArray bits)
    {
        byte[] ret = new byte[(bits.Length - 1) / 8 + 1];
        bits.CopyTo(ret, 0);
        return ret;
    }
    

    适用于:

    string text = "Test";
    byte[] bytes = System.Text.Encoding.ASCII.GetBytes(text);
    BitArray bits = new BitArray(bytes);
    bytes[] bytesBack = BitArrayToByteArray(bits);
    string textBack = System.Text.Encoding.ASCII.GetString(bytesBack);
    // bytes == bytesBack
    // text = textBack
    

    .

    【讨论】:

    • 而不是“bits.Length / 8”,你应该使用“(bits.Length - 1)/ 8 + 1”,否则如果BitArray的长度为7,你的字节数组将是空的。 “- 1”部分确保 8 的倍数不会返回加一。感谢stackoverflow.com/questions/17944/…
    • 好点。我猜 A Math.Max(1, bits.Length / 8) 也可以工作(可读性略强)。我总是在 8 位字节上操作,所以我没有考虑下溢情况。
    • @TeddHansen 15 岁怎么样?
    • 这不处理空的情况,请注意 - 可能需要添加一个检查 bits 何时为空并相应地返回一个空的 byte[] 数组。
    • 应为“byte[(bits.Length - 1) / 8 - 1”,否则在字节数组末尾添加不必要的“0”字节。
    【解决方案3】:

    穷人的解决方案:

    protected byte ConvertToByte(BitArray bits)
    {
        if (bits.Count != 8)
        {
            throw new ArgumentException("illegal number of bits");
        }
    
        byte b = 0;
        if (bits.Get(7)) b++;
        if (bits.Get(6)) b += 2;
        if (bits.Get(5)) b += 4;
        if (bits.Get(4)) b += 8;
        if (bits.Get(3)) b += 16;
        if (bits.Get(2)) b += 32;
        if (bits.Get(1)) b += 64;
        if (bits.Get(0)) b += 128;
        return b;
    }
    

    【讨论】:

      【解决方案4】:

      这应该可以解决问题。但是,以前的答案很可能是更好的选择。

          public byte ConvertToByte(BitArray bits)
          {
              if (bits.Count > 8)
                  throw new ArgumentException("ConvertToByte can only work with a BitArray containing a maximum of 8 values");
      
              byte result = 0;
      
              for (byte i = 0; i < bits.Count; i++)
              {
                  if (bits[i])
                      result |= (byte)(1 << i);
              }
      
              return result;
          }
      

      在您发布的示例中,生成的字节将为 0x80。换句话说,BitArray 中的第一个值对应于返回字节中的第一位。

      【讨论】:

      • 这不会在0 位上左移result,是吗?
      【解决方案5】:

      不幸的是,BitArray 类在 .Net Core 类 (UWP) 中部分实现。例如 BitArray 类无法调用 CopyTo() 和 Count() 方法。我写了这个扩展来填补空白:

      public static IEnumerable<byte> ToBytes(this BitArray bits, bool MSB = false)
      {
          int bitCount = 7;
          int outByte = 0;
      
          foreach (bool bitValue in bits)
          {
              if (bitValue)
                  outByte |= MSB ? 1 << bitCount : 1 << (7 - bitCount);
              if (bitCount == 0)
              {
                  yield return (byte) outByte;
                  bitCount = 8;
                  outByte = 0;
              }
              bitCount--;
          }
          // Last partially decoded byte
          if (bitCount < 7)
              yield return (byte) outByte;
      }
      

      该方法使用 LSB(低有效字节)逻辑将 BitArray 解码为字节数组。这与 BitArray 类使用的逻辑相同。调用将 MSB 参数设置为 true 的方法将生成 MSB 解码字节序列。在这种情况下,请记住,您可能还需要反转最终的输出字节集合。

      【讨论】:

        【解决方案6】:

        这应该是最终的。适用于任何长度的数组。

        private List<byte> BoolList2ByteList(List<bool> values)
            {
        
                List<byte> ret = new List<byte>();
                int count = 0;
                byte currentByte = 0;
        
                foreach (bool b in values) 
                {
        
                    if (b) currentByte |= (byte)(1 << count);
                    count++;
                    if (count == 7) { ret.Add(currentByte); currentByte = 0; count = 0; };              
        
                }
        
                if (count < 7) ret.Add(currentByte);
        
                return ret;
        
            }
        

        【讨论】:

        • 我相信这里有一个错误 - 因为count++; 已经触发,下一行应该是if (count == 8) {...}
        【解决方案7】:

        除了@JonSkeet 的回答,您还可以使用如下扩展方法:

        public static byte ToByte(this BitArray bits)
        {
            if (bits.Count != 8)
            {
                throw new ArgumentException("bits");
            }
            byte[] bytes = new byte[1];
            bits.CopyTo(bytes, 0);
            return bytes[0];
        }
        

        并像这样使用:

        BitArray foo = new BitArray(new bool[]
        {
            false, false, false, false,false, false, false, true
        });
        
        foo.ToByte();
        

        【讨论】:

          【解决方案8】:
          byte GetByte(BitArray input)
          {
            int len = input.Length;
            if (len > 8)
              len = 8;
            int output = 0;
            for (int i = 0; i < len; i++)
              if (input.Get(i))
                output += (1 << (len - 1 - i)); //this part depends on your system (Big/Little)
                //output += (1 << i); //depends on system
            return (byte)output;
          }
          

          干杯!

          【讨论】:

            【解决方案9】:

            小端字节数组转换器:BitArray 中的第一位(索引为“0”) 假定表示最低有效位(位八位字节中的最右边位),将其解释为二进制的“零”或“一”。

             public static class BitArrayExtender {
            
                public static byte[] ToByteArray( this BitArray bits ) {
            
                    const int BYTE = 8;
                    int length = ( bits.Count / BYTE ) + ( (bits.Count % BYTE == 0) ? 0 : 1 );
                    var bytes  = new byte[ length ];
            
                    for ( int i = 0; i < bits.Length; i++ ) {
            
                       int bitIndex  = i % BYTE;
                       int byteIndex = i / BYTE;
            
                       int mask = (bits[ i ] ? 1 : 0) << bitIndex;
                       bytes[ byteIndex ] |= (byte)mask;
            
                    }//for
            
                    return bytes;
            
                }//ToByteArray
            
             }//class
            

            【讨论】:

              猜你喜欢
              • 2015-08-04
              • 1970-01-01
              • 2019-12-13
              • 2011-02-02
              • 1970-01-01
              • 2011-06-12
              • 2010-09-26
              • 2010-10-17
              相关资源
              最近更新 更多