C# 将 bool[] 转换为 byte[]

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/713057/
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:05:04  来源:igfitidea点击:

Convert bool[] to byte[]

c#booleanbytearray

提问by

I have a List<bool>which I want to convert to a byte[]. How do i do this? list.toArray()creates a bool[].

我有一个List<bool>我想转换为byte[]. 我该怎么做呢? list.toArray()创建一个bool[].

采纳答案by Marc Gravell

Here's two approaches, depending on whether you want to pack the bits into bytes, or have as many bytes as original bits:

这里有两种方法,具体取决于您是想将位打包成字节,还是拥有与原始位一样多的字节:

    bool[] bools = { true, false, true, false, false, true, false, true,
                     true };

    // basic - same count
    byte[] arr1 = Array.ConvertAll(bools, b => b ? (byte)1 : (byte)0);

    // pack (in this case, using the first bool as the lsb - if you want
    // the first bool as the msb, reverse things ;-p)
    int bytes = bools.Length / 8;
    if ((bools.Length % 8) != 0) bytes++;
    byte[] arr2 = new byte[bytes];
    int bitIndex = 0, byteIndex = 0;
    for (int i = 0; i < bools.Length; i++)
    {
        if (bools[i])
        {
            arr2[byteIndex] |= (byte)(((byte)1) << bitIndex);
        }
        bitIndex++;
        if (bitIndex == 8)
        {
            bitIndex = 0;
            byteIndex++;
        }
    }

回答by Richard Watson

If you have any control over the type of list, try to make it a List, which will then produce the byte[] on ToArray(). If you have an ArrayList, you can use:

如果您对列表的类型有任何控制,请尝试将其设为列表,然后在 ToArray() 上生成 byte[]。如果你有一个 ArrayList,你可以使用:

(byte[])list.ToArray(typeof(byte));

To get the List, you could create one with your unspecified list iterator as an input to the constructor, and then produce the ToArray()? Or copy each item, casting to a new byte from bool?

要获取列表,您可以使用未指定的列表迭代器创建一个列表作为构造函数的输入,然后生成 ToArray()? 或者复制每个项目,从 bool 转换到一个新字节?

Some info on what type of list it is might help.

关于它是什么类型的列表的一些信息可能会有所帮助。

回答by dommer

Have a look at the BitConverterclass. Depending on the exact nature of your requirement, it may solve your problem quite neatly.

看看BitConverter类。根据您的要求的确切性质,它可能会非常巧妙地解决您的问题。

回答by hfcs101

You can use LINQ. This won't be efficient, but will be simple. I'm assuming that you want one byte per bool.

您可以使用 LINQ。这不会有效,但会很简单。我假设你想要每个布尔值一个字节。

bool[] a = new bool[] { true, false, true, true, false, true };
byte[] b = (from x in a select x ? (byte)0x1 : (byte)0x0).ToArray();

回答by johnildergleidisson

Another LINQ approach, less effective than @hfcs101's but would easily work for other value types as well:

另一种 LINQ 方法,不如 @hfcs101 有效,但也很容易适用于其他值类型:

var a = new [] { true, false, true, true, false, true };
byte[] b = a.Select(BitConverter.GetBytes).SelectMany(x => x).ToArray();

回答by AnorZaken

Marc's answer is good already, but...

马克的回答已经很好了,但是......

Assumingyou are the kind of person that is comfortable doing bit-twiddling, or just want to write less code andsqueeze out some more performance, then this here code is for you good sir / madame:

假设你是那种喜欢做一些小事的人,或者只是想写更少的代码挤出更多的性能,那么这里的代码是给你的好先生/女士:

byte[] PackBoolsInByteArray(bool[] bools)
{
    int len = bools.Length;
    int bytes = len >> 3;
    if ((len & 0x07) != 0) ++bytes;
    byte[] arr2 = new byte[bytes];
    for (int i = 0; i < bools.Length; i++)
    {
        if (bools[i])
            arr2[i >> 3] |= (byte)(1 << (i & 0x07));
    }
}

It does the exact same thing as Marc's code, it's just more succinct.

它与 Marc 的代码完全相同,只是更简洁。

Of course if we reallywant to go all out we could unroll it too...
...and while we are at it lets throw in a curve ball on the return type!

当然,如果我们真的想全力以赴,我们也可以展开它
......当我们在它的时候,让我们在返回类型上扔一个曲线球!

IEnumerable<byte> PackBoolsInByteEnumerable(bool[] bools)
{
    int len = bools.Length;
    int rem = len & 0x07; // hint: rem = len % 8.

    /*
    byte[] byteArr = rem == 0 // length is a multiple of 8? (no remainder?)
        ? new byte[len >> 3] // -yes-
        : new byte[(len >> 3)+ 1]; // -no-
     */

    const byte BZ = 0,
        B0 = 1 << 0, B1 = 1 << 1, B2 = 1 << 2, B3 = 1 << 3,
        B4 = 1 << 4, B5 = 1 << 5, B6 = 1 << 6, B7 = 1 << 7;

    byte b;
    int i = 0;
    for (int mul = len & ~0x07; i < mul; i += 8) // hint: len = mul + rem.
    {
        b = bools[i] ? B0 : BZ;
        if (bools[i + 1]) b |= B1;
        if (bools[i + 2]) b |= B2;
        if (bools[i + 3]) b |= B3;
        if (bools[i + 4]) b |= B4;
        if (bools[i + 5]) b |= B5;
        if (bools[i + 6]) b |= B6;
        if (bools[i + 7]) b |= B7;

        //byteArr[i >> 3] = b;
        yield return b;
    }

    if (rem != 0) // take care of the remainder...
    {
        b = bools[i] ? B0 : BZ; // (there is at least one more bool.)

        switch (rem) // rem is [1:7] (fall-through switch!)
        {
            case 7:
                if (bools[i + 6]) b |= B6;
                goto case 6;
            case 6:
                if (bools[i + 5]) b |= B5;
                goto case 5;
            case 5:
                if (bools[i + 4]) b |= B4;
                goto case 4;
            case 4:
                if (bools[i + 3]) b |= B3;
                goto case 3;
            case 3:
                if (bools[i + 2]) b |= B2;
                goto case 2;
            case 2:
                if (bools[i + 1]) b |= B1;
                break;
            // case 1 is the statement above the switch!
        }

        //byteArr[i >> 3] = b; // write the last byte to the array.
        yield return b; // yield the last byte.
    }

    //return byteArr;
}

Tip:As you can see I included the code for returning a byte[]as comments. Simply comment out the two yield statements instead if that is what you want/need.

提示:如您所见,我包含了将 abyte[]作为注释返回的代码。如果这是您想要/需要的,只需注释掉两个 yield 语句即可。



Twiddling Hints:
Shifting x >> 3is a cheaper x / 8.
Masking x & 0x07is a cheaper x % 8.
Masking x & ~0x07is a cheaper x - x % 8.

Twiddling Hints:
换档x >> 3更便宜x / 8
掩蔽x & 0x07是更便宜的x % 8
掩蔽x & ~0x07是更便宜的x - x % 8



Edit:Here is some example documentation:

编辑:这是一些示例文档:

    /// <summary>
    /// Bit-packs an array of booleans into bytes, one bit per boolean.
    /// </summary><remarks>
    /// Booleans are bit-packed into bytes, in order, from least significant
    /// bit to most significant bit of each byte.<br/>
    /// If the length of the input array isn't a multiple of eight, then one
    /// or more of the most significant bits in the last byte returned will
    /// be unused. Unused bits are zero / unset.
    /// </remarks>
    /// <param name="bools">An array of booleans to pack into bytes.</param>
    /// <returns>
    /// An IEnumerable&lt;byte&gt; of bytes each containing (up to) eight
    /// bit-packed booleans.
    /// </returns>

回答by Bruno Zell

Or the IEnumerableapproach to AnorZaken's answer:

或者IEnumerableAnorZaken 的回答的方法:

static IEnumerable<byte> PackBools(IEnumerable<bool> bools)
{
    int bitIndex = 0;
    byte currentByte = 0;
    foreach (bool val in bools) {
        if (val)
            currentByte |= (byte)(1 << bitIndex);
        if (++bitIndex == 8) {
            yield return currentByte;
            bitIndex = 0;
            currentByte = 0;
        }
    }
    if (bitIndex != 8) {
        yield return currentByte;
    }
}

And the according unpacking where paddingEndmeans the amount of bits to discard from the last byte to unpack:

并且相应的解包 wherepaddingEnd表示从要解包的最后一个字节丢弃的位数:

static IEnumerable<bool> UnpackBools(IEnumerable<byte> bytes, int paddingEnd = 0)
{
    using (var enumerator = bytes.GetEnumerator()) {
        bool last = !enumerator.MoveNext();
        while (!last) {
            byte current = enumerator.Current;
            last = !enumerator.MoveNext();
            for (int i = 0; i < 8 - (last ? paddingEnd : 0); i++) {
                yield return (current & (1 << i)) != 0;
            }
        }
    }
}