C# 将布尔[]转换为字节[]
我有一个C# 将布尔[]转换为字节[],c#,boolean,bytearray,C#,Boolean,Bytearray,我有一个列表,我想将其转换为字节[]。我该怎么做? list.toArray()创建一个bool[]这里有两种方法,具体取决于您是要将位打包为字节,还是要将字节数与原始位的字节数相同: bool[] bools = { true, false, true, false, false, true, false, true, true }; // basic - same count byte[] arr1 = Array.Conv
列表
,我想将其转换为字节[]
。我该怎么做?
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++;
}
}
bool[]bools={true,false,true,false,true,false,true,
真};
//基本-相同计数
字节[]arr1=Array.ConvertAll(bools,b=>b?(字节)1:(字节)0);
//打包(在本例中,使用第一个bool作为lsb-如果您愿意
//第一个bool作为msb,颠倒事物;-p)
int bytes=bools.Length/8;
如果((bools.Length%8)!=0)字节++;
字节[]arr2=新字节[字节];
int-bitIndex=0,byteIndex=0;
for(int i=0;i arr2[byteIndex]|=(byte)((byte)1)如果您可以控制列表的类型,请尝试将其设置为列表,然后将在ToArray()上生成字节[]。如果您有ArrayList,则可以使用:
(byte[])list.ToArray(typeof(byte));
要获取列表,可以使用未指定的列表迭代器创建一个列表,作为构造函数的输入,然后生成ToArray()?或复制每个项,从bool转换为新字节
关于它是什么类型的列表的一些信息可能会有所帮助。看看这个类。根据您需求的确切性质,它可能会非常巧妙地解决您的问题。您可以使用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();
另一种LINQ方法,不如@hfcs101有效,但也很容易适用于其他值类型:
var a = new [] { true, false, true, true, false, true };
byte[] b = a.Select(BitConverter.GetBytes).SelectMany(x => x).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));
}
}
或IEnumerable
方法:
你想让3个bool变成1字节还是3字节?在输入数组开始有数千个条目之前,我不认为这会特别低效。这不起作用。它将返回位数组。(bool数组)而不是字节。False(-1)为有符号字节返回255。你可以通过以下方法一步计算字节:int bytes=(bools.Length+7)/8;
使第二个增量行冗余。速度也更快(与除法+模数相比,仅一个除法)伟大的方法-我会删除基本方法。这是一种浪费内存的方法,字节
不是用来存储一个位
@fubo的。虽然我同意你的观点,但这确实是一个意图问题:如果这是需要的,那么它就是需要的好代码。它似乎有一个bug/typo,但是在PackBools()中,它读作(bitIndex!=8),但它永远也不能==8,因为上面的代码已经检查了这个条件if(++bitIndex==8)并设置了bitIndex=0。因此它很可能应该在下一个新字节的开头读取if(bitIndex!=0)。
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;
}
/// <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<byte> of bytes each containing (up to) eight
/// bit-packed booleans.
/// </returns>
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;
}
}
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;
}
}
}
}