C# 如何将位转换为字节?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/719502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:23:11  来源:igfitidea点击:

How can I convert bits to bytes?

c#bit-manipulationbyte

提问by David Brown

I have an array of 128 booleans that represent bits. How can I convert these 128 bit representations into 16 bytes?

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

Example:

例子:

I have an array that looks like this:

我有一个看起来像这样的数组:

0110001100110000100010111011001011010011010001010001101101001100
1000010000000000001000111111111101000011111001111011111011111001

(Converted to 1s and 0s to be more concise)

(转换为 1 和 0 更简洁)

I need to convert those bits to the following byte array:

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

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

EDIT: This doesn't seem to work:

编辑:这似乎不起作用:

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

It outputs:

它输出:

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

采纳答案by CAdaker

The code is treating the first bit as the low bit of the word, so you end up with each word reversed. As a quick-and-dirty fix, try this:

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

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

That puts the first bit in the array at the highest position in the first byte, etc.

这会将数组中的第一位放在第一个字节的最高位置,依此类推。

回答by Brian R. Bondy

I don't know if there's an automatic way to do it, but you can do it with a simple algorithm.

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

Simple algorithm:

简单算法:

  1. Create an array of bytes that will be used as your output buffer, and initialize all bytes to 0. The size of this array should be based on the length of your input boolean array: ceil(bool_array_length / 8.0)

  2. Declare an index variable to be used as your current byte, and set it to 0. This holds the index in your output buffer.

  3. Iterate over each element in your input boolean array.
    3.1. Left bit shift the number 1 by the array index mod 8. Call this number your mask.
    3.2. Calculate your byte index as your current index into the array div 8.
    3.3. If you have a boolean truevalue the current index in your input boolean array, do a bitwise ORwith your current byte and your mask.

  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使用当前字节和掩码。

回答by Noldorin

Try this function (written as an extension method).

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

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

Note: It will fail if the number of bits (bools) is not a multiple of 8, but judging by your question this isn't the case. It would only take a very small modificaiton to permit bit arrays of any length.

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

回答by Lucas

bool[] bools = ...
BitArray a = new BitArray(bools);
byte[] bytes = new byte[a.Length / 8];
a.CopyTo(bytes, 0);


EDIT: Actually this also returns:

编辑:实际上这也返回:

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

Wrong endianness? I'll leave answer anyway, for reference.

错误的字节序?反正我会留下答案,以供参考。



EDIT: You can use BitArray.CopyTo() by reversing the arrays like so:

编辑:您可以通过像这样反转数组来使用 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);

回答by drayv

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