将bool 转换为byte

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

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

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

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

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

马克的答案已经很好,但……

假设你是那种习惯于吵吵嚷嚷的人,或者只是想写更少的代码挤出更多的性能,那么这里的代码对你来说是好的先生/女士:

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

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

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

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

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


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


编辑:以下是一些示例文档:

  ///  /// Bit-packs an array of booleans into bytes, one bit per boolean. ///  /// Booleans are bit-packed into bytes, in order, from least significant /// bit to most significant bit of each byte.
/// 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. ///
/// An array of booleans to pack into bytes. /// /// An IEnumerable<byte> of bytes each containing (up to) eight /// bit-packed booleans. ///

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

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

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

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

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

另一种LINQ方法,效率低于@ hfcs101,但也适用于其他值类型:

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

或者是AnnZaken答案的IEnumerable方法:

 static IEnumerable PackBools(IEnumerable 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; } } 

并解paddingEnd表示从最后一个字节丢弃的位数以解压缩:

 static IEnumerable UnpackBools(IEnumerable 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; } } } }