【问题标题】:Convert unknow Bits from Byte array to int将未知位从字节数组转换为 int
【发布时间】:2011-06-12 16:13:27
【问题描述】:
private int bitToIntParser
(byte[] recordData, int byteOffset, int byteLength, int bitOffset, int bitLength)
        {
            //step1:Byte[] selectedBytes = recordData[byteOffset to byteOffset + Length]  
            //step2:BitArray selectedBits=selectdBytes.bits[bitOffset to bitOffset+bitLength]
            //step3:convert selectedBit to Int          
        }

上面的函数应该可以从recordData中提取bytes[byteOffset]bytes[byteOffset+length],然后再从之前的结果中提取bit[bitOffset]bit[bitOffset+BitLength],再转换成int

谁能帮我解决这个问题?

【问题讨论】:

  • 对于第 1 步,我使用了 byte[] workingSet = new byte[4]; Buffer.BlockCopy(recordData, byteOffset, workingSet, 0, length);但后来我不确定如何从中提取请求的位,我尝试移位但无法获得结果
  • 对 bitOffset 和 bitLength 参数有什么限制吗?
  • @Henk : 它不应该超过 32 位,所以我们可以使用 BitVector32
  • 这样输入的正确结果是什么?记录数据:{00001111b 11110000b} byteOffset:0 byteLength:2 bitOffset:4 bitLength:8

标签: c# .net binary bit-manipulation math


【解决方案1】:

哇,这变成了一些非常混乱的代码。我们必须手动进行位移,因为您可能可能在此操作中涉及超过四个字节,具体取决于您的位位置。假设小端字节序(LSB 在前):

// No need for byte length, since you're passing in a bit count
private int ParseByteArray(byte[] recordData, int offset, int bitOffset, 
       int bitCount)
{
    if(bitCount < 1 || bitCount > 32) 
    {
        throw new ArgumentException("bitCount must be between 1 and 32");
    }

     int output = 0;
    int byteCount = 0;

    byte rightMask = (byte)(((1 << bitOffset) - 1) << (8 - bitOffset));
    byte leftMask = (byte)(255 ^ rightMask);

    while (bitCount > 0)
    {
        byte data = (byte)(((recordData[offset] & leftMask) << bitOffset) + 
                    ((bitCount > 8 - bitOffset ? 
                    ((recordData[offset + 1] & rightMask) >> (8 - bitOffset)) 
                    : 0)));

        if (bitCount < 8)
        {
            byte mask = (byte)(255^((1 << (8 - bitCount)) - 1));

            data = (byte)((data & mask) >> (8 - bitCount));
        }

        offset++;

        output += data << (byteCount * 8);

        byteCount++;

        bitCount -= Math.Min(bitCount, 8);
    }

    return output;
}

【讨论】:

  • ParseByteArray(new byte[]{0xFF, 0xA},1,4,3) // 失败 (
【解决方案2】:

在我看来,byteLength 和 bitLength 是多余的(偏移量也是如此)。

但就目前而言,我会说:

  • 制作一个 8 字节的中间数组
  • 将 byteLength 字节 (1..4) 复制到该数组,可能从偏移 7-byteLength 开始
  • 使用 BitConvertor.ToInt64() 将其变成long
  • value = (int) (longValue >> bitOffset)

这仍然是开放式的(您期望有符号或无符号的 int32 吗?)

我没有对此进行测试,您也可能有字节序问题。

【讨论】:

  • byteLength 是多余的,但不一定是bitOffset。虽然您可以用位表示整个偏移量(使其真正冗余),但我将其作为位偏移量在一个字节内从数字开始,这意味着最后的 8-bitOffset 位来自第一个下一个字节的 8-bitOffset 位。
  • @Adam: byteOffset 和 bitOffset 可以很容易地组合。长度的相关性更强。这将是一个“更好”的界面,只有一个位范围
  • 由于性能原因,我需要字节长度,recordData 可能是一个大数组。而且我还需要 BitLength 因为我们可能只需要一个字节中的第 2 位和第 3 位,所以我们将使用 bitoffset = 2 和 bitLength = 2 调用该函数,我认为您解释的方式不会像我刚才解释的那样起作用
  • @Asna:你总是需要byteLength == (bitLength+7) / 8。但你是对的,我的解决方案不会掩盖左边的位。我会留在这里。
猜你喜欢
  • 2011-09-04
  • 2010-10-22
  • 1970-01-01
  • 2023-03-03
  • 2022-06-20
  • 2010-10-08
  • 2019-12-13
相关资源
最近更新 更多