You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 03:53:18