C#如何实现向MemoryStream写入指定长度比特位的WriteBits方法
C# 比特位写入MemoryStream实现方案
要实现比特级打包写入MemoryStream,首先需要明确:MemoryStream本身只支持字节为单位的写入操作,因此需要额外维护两个状态,用来暂存未写满的字节和填充进度。
完整实现代码
上下文需要的成员定义
private readonly MemoryStream _ms = new MemoryStream(); // 当前正在填充的未完成字节缓存 private byte _currentByte; // 当前字节已填充的比特数(取值范围0-7) private int _bitOffset; // 预定义掩码:_bitMask[n] 代表n个比特位的全1掩码,n范围1-8 private static readonly int[] _bitMask = { 0, 0b1, 0b11, 0b111, 0b1111, 0b11111, 0b111111, 0b1111111, 0b11111111 };
WriteBits核心方法
void WriteBits(int numBits, int value) { // 参数合法性校验 if (numBits < 1 || numBits > 32) throw new ArgumentOutOfRangeException(nameof(numBits), "比特位长度需在1-32之间"); if (value < 0) throw new ArgumentOutOfRangeException(nameof(value), "当前实现暂不支持写入负数"); // 提前截断超出指定比特位长度的无效数值部分 if(numBits <= 8) value &= _bitMask[numBits]; while (numBits > 0) { int remainingBitsInCurrentByte = 8 - _bitOffset; int takeBits = Math.Min(numBits, remainingBitsInCurrentByte); // 取出本次要写入的比特段,移动到当前字节对应的位置 int writePart = (value & (_bitMask[takeBits] << (numBits - takeBits))) >> (numBits - takeBits); _currentByte = (byte)(_currentByte | (writePart << (remainingBitsInCurrentByte - takeBits))); // 更新计数状态 numBits -= takeBits; _bitOffset += takeBits; // 当前字节已填充满,写入流并重置临时状态 if (_bitOffset == 8) { _ms.WriteByte(_currentByte); _currentByte = 0; _bitOffset = 0; } } }
收尾Flush方法
所有比特写入完成后需要调用该方法,将最后未写满的字节补0后写入流:
void FlushBits() { if (_bitOffset > 0) { _ms.WriteByte(_currentByte); _currentByte = 0; _bitOffset = 0; } }
使用示例
和你提供的代码框架完全兼容:
// 先写入5个值为1的字节 _ms.WriteByte(1); _ms.WriteByte(1); _ms.WriteByte(1); _ms.WriteByte(1); _ms.WriteByte(1); WriteBits(2, 3); // 写入2比特,值为3(二进制11) WriteBits(1, 1); // 写入1比特,值为1 // 所有写入完成后执行收尾 FlushBits();
逻辑说明
该实现和你提供的Java参考实现逻辑完全对齐,核心思路都是分批次将长比特值拆分写入多个字节,暂存未写满的部分等待后续填充,避免空间浪费,完全满足网络传输场景下的比特打包性能要求。
内容的提问来源于stack exchange,提问作者Jess Chan
相关产品推荐
相关产品推荐

