如何从byte[]中优雅高效读取非字节对齐的n位(n≤8)值?
从
byte[]中读取非对齐的n位值(n≤8) 需要从byte[]中读取长度为n位(n≤8)的值,该值可能不与字节首尾对齐,甚至跨两个字节。示例如下:
// __ ___ ## # var bytes = new byte[] { 0b_1111_1100, 0b_0001_1111, 0b_1100_0111 };
我希望将跨两个字节的5个0(标记为_)和另一组3位(标记为#)读取为byte/int类型。
我尝试了两种方法:一是通过位运算手动计算,但实现繁琐;二是使用BitArray类,但该类无直接对应方法,手动累加位的方式不够优雅。以下是两种方法的实现代码:
方法一:位运算计算
var bytes = new byte[] { 0b_1111_1100, 0b_0001_1111, 0b_1100_0111 }; Console.WriteLine("5bit value: " + GetNBitsFromByteArray(bytes, 0, 6, 5)); Console.WriteLine("3bit value: " + GetNBitsFromByteArray(bytes, 2, 2, 3)); int GetNBitsFromByteArray(byte[] bytes, int startByte, int startBit, int length) { if (startBit + length <= 8) { // 整个值在单个字节内 return GetBitsFromByte(bytes[startByte], startBit, length); } else { // 值跨两个字节 var lengthInByte1 = 8 - startBit; var part1 = GetBitsFromByte(bytes[startByte], startBit, lengthInByte1); var part2 = GetBitsFromByte(bytes[startByte + 1], 0, length - lengthInByte1); return (part1 << lengthInByte1) + part2; } } // startBit是选择开始的位索引,0为最高位,7为最低位。例如:GetBitsFromByte(0b_0001_1110, 3, 4) == 15 int GetBitsFromByte(byte byteValue, int startBit, int length) { var mask = (1 << 8 - startBit) - (1 << 8 - startBit - length); return byteValue & mask; }
方法二:使用BitArray
BitArray bits = new(new byte[] { 0b_1111_1100, 0b_0001_1111, 0b_1100_0111 }); Console.WriteLine("First ones: " + Get5BitValue(bits, 6)); Console.WriteLine("Second ones: " + Get3BitValue(bits, 18)); int Get5BitValue(BitArray bits, int startBitIndex) { return (bits[startBitIndex + 0] ? 16 : 0) + (bits[startBitIndex + 1] ? 8 : 0) + (bits[startBitIndex + 2] ? 4 : 0) + (bits[startBitIndex + 3] ? 2 : 0) + (bits[startBitIndex + 4] ? 1 : 0); } int Get3BitValue(BitArray bits, int startBitIndex) { return (bits[startBitIndex + 0] ? 4 : 0) + (bits[startBitIndex + 1] ? 2 : 0) + (bits[startBitIndex + 2] ? 1 : 0); }
我知道可以通过循环实现通用的GetNBitValue方法,但上述示例为了可读性未采用。请问是否存在更优雅或更高效的实现方式?注:所有代码基于.NET7编写并测试。
内容的提问来源于stack exchange,提问作者Lynn
相关产品推荐
相关产品推荐

