【问题标题】:How can I convert bits to bytes?如何将位转换为字节?
【发布时间】:2010-10-17 16:44:28
【问题描述】:

我有一个代表位的 128 个布尔值数组。如何将这些 128 位表示形式转换为 16 字节?

例子:

我有一个如下所示的数组:

0110001100110000100010111011001011010011010001010001101101001100
1000010000000000001000111111111101000011111001111011111011111001

(转换为 1 和 0 更简洁)

我需要将这些位转换为以下字节数组:

99 48 139 178 211 69 27 76 132 0 35 255 67 231 190 249

编辑:这似乎不起作用:

public byte[] ToByteArray() {
    int numBytes = 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 << bitIndex);

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

    return bytes;
}

它输出:

198 12 209 77 203 162 216 50 33 0 196 255 194 231 125 159

【问题讨论】:

  • 您可以使用模 (%) 运算符消除“byteIndex”变量。字节[bitIndex % 8]
  • @arul,我怀疑你在考虑整数除法。必须在分配的右侧使用模数。 bytes[bitIndex / 8] |= (byte)(1 &lt;&lt; (bitIndex % 8))

标签: c# bit-manipulation byte


【解决方案1】:
private static byte[] GetBytes(string bitString)
{
    byte[] result = Enumerable.Range(0, bitString.Length / 8).
        Select(pos => Convert.ToByte(
            bitString.Substring(pos * 8, 8),
            2)
        ).ToArray();

    List<byte> mahByteArray = new List<byte>();
    for (int i = result.Length - 1; i >= 0; i--)
    {
        mahByteArray.Add(result[i]);
    }

    return mahByteArray.ToArray();
}

private static String ToBitString(BitArray bits)
{
    var sb = new StringBuilder();

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

    return sb.ToString();
}

【讨论】:

    【解决方案2】:

    试试这个函数(写成扩展方法)。

    public byte[] ToByteArray(this bool[] bits)
    {
        var bytes = new byte[bits.Length / 8];
        for (int i = 0, j = 0; j < bits.Length; i++, j += 8)
        {
            // Create byte from bits where LSB is read first.
            for (int offset = 0; offset < 8; offset++)
                bytes[i] |= (bits[j + offset] << offset);
        }
    
        return bytes;
    }
    

    注意:如果位数(布尔值)不是 8 的倍数,它将失败,但根据您的问题判断,情况并非如此。只需要很小的修改就可以允许任何长度的位数组。

    【讨论】:

    • 你的意思是“bytes[i] |= (bits[j + offset]
    【解决方案3】:
    bool[] bools = ...
    BitArray a = new BitArray(bools);
    byte[] bytes = new byte[a.Length / 8];
    a.CopyTo(bytes, 0);
    

    编辑:实际上这也返回:

    198 12 209 77 203 162 216 50 33 0 196 255 194 231 125 159
    

    错误的字节顺序?无论如何我都会留下答案,以供参考。


    编辑:您可以通过反转数组来使用 BitArray.CopyTo(),如下所示:

    bool[] bools = ...
    Array.Reverse(bools); // NOTE: this modifies your original array
    BitArray a = new BitArray(bools);
    byte[] bytes = new byte[a.Length / 8];
    a.CopyTo(bytes, 0);
    Array.Reverse(bytes);
    

    【讨论】:

      【解决方案4】:

      代码将第一位视为单词的低位,因此您最终会反转每个单词。作为一个快速而肮脏的修复,试试这个:

      bytes[byteIndex] |= (byte)(1 << (7-bitIndex));
      

      将数组中的第一位放在第一个字节的最高位置,等等。

      【讨论】:

        【解决方案5】:

        我不知道是否有自动的方法可以做到这一点,但你可以用一个简单的算法来做到这一点。

        简单算法:

        1. 创建将用作输出缓冲区的字节数组,并将所有字节初始化为 0。此数组的大小应基于输入布尔数组的长度:ceil(bool_array_length / 8.0)

        2. 声明一个索引变量用作当前字节,并将其设置为 0。这会将索引保存在输出缓冲区中。

        3. 遍历输入布尔数组中的每个元素。
          3.1。将数字 1 左移数组索引 mod 8。将此数字称为掩码。
          3.2.将字节索引计算为数组 div 8 中的当前索引。
          3.3.如果您有一个布尔值 true 值作为输入布尔数组中的当前索引,请使用您的当前字节和掩码执行 bitwise OR

        【讨论】:

          猜你喜欢
          • 2010-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-05
          • 2018-05-06
          相关资源
          最近更新 更多