【问题标题】:bitarray to byte array possible endian issues位数组到字节数组可能的字节序问题
【发布时间】:2022-02-08 08:01:45
【问题描述】:

我想在 azure blob 存储中存储一系列 bool 值以及一个单独的映射文件(一个逗号分隔的名称列表,与 bool 值的顺序相同)。

由于效率和存储是重要因素,我想将 bool 值存储为字节数组。

我已经通过构造一个位数组来解决这个问题,然后我使用位数组 CopyTo 将其复制到一个字节数组中。我已经通过使用 new BitArray(mybytearray) 将其转换回来并比较结果进行了本地测试,结果匹配良好。

我的问题是,这段代码是否可靠?还是特定于环境/硬件?大/小端在这里生效吗?当我将它部署到在 Windows 上运行的 azure 服务时,它的运行方式是否相同?运行linux vm会导致字节序创建错误的输出吗? (一个单独的 azure 服务实际上是从 blob 读取的,但它应该配置相同,即 windows/plan)

我有点困惑,虽然我的代码似乎工作正常,但下面的 SO 帖子接受的答案有 cmets 说 bitarray 写入 bytearray 的方式顺序将被颠倒,所以你应该在放置之前专门反转数组进入字节数组。 Convert from BitArray to Byte

这是我的逻辑的最小代码示例(我的案例有数十万个布尔值):

     var boolarr = new bool[] { true, true, false, false, false };
            var bitarr = new BitArray(boolarr);
            var length = bitarr.Length / 8;
            if (bitarr.Length % 8 > 0)
                length += 1;
            var bytearray = new byte[length];
            bitarr.CopyTo(bytearray, 0);
            BitArray bits = new BitArray(bytearray);

//Below just checking the above is working properly
            for (var i = 0; i < bits.Length; i++)
            {
                if (i >= bitarr.Length)
                    break;//last byte may not be using all bits
                if (bits[i] != bitarr[i])
                {
                    throw new Exception();//This would be bad.
                }
            }

【问题讨论】:

  • 你的小布尔数组在什么情况下会使用过多的资源?这看起来像是解决一个不存在的问题的不必要的微优化。
  • 所以这里的目标只是将bool[] 表示为byte[],只是为了节省一点存储空间(.NET bool 是 32 位,而 byte 是 8 位,这就是想法?) - BitArray 来自哪里?为什么不直接去bool[] -> byte[]
  • @CoolBots 看起来他们正在尝试使用每个字节中的每一位,从而有效地将数据大小减少了 8 倍。布尔在 C# 中是 1 个字节
  • @NigelBess 那么 OP 的文章中一定有一个错误 - “由于效率和存储是重要因素,我想将 bool 值存储为 byte 数组。 ”。另外,你是对的,boolbyte 大小相同...
  • 字节顺序只对多字节值起作用。字节数组在任何平台上都以相同的顺序存储,字节中位的物理顺序对高级语言是不透明的。

标签: c# arrays endianness bitarray


【解决方案1】:

我认为代码将是特定于硬件的,但老实说,我不知道BitArray 的内部工作原理,也不能肯定地告诉你。但我可以给你一些不管硬件/环境如何都能工作的代码:

private const int bitsPerByte = 8;
public static byte[] ToByteArray(bool[] bits)
{
    var bitCount = bits.Length;
    var byteCount = bitCount / bitsPerByte ;
    if (bitCount - byteCount*bitsPerByte  > 0) byteCount += 1;
    var bytes = new byte[byteCount];
    for (int i = 0; i < bitCount; i++)
    {
        SetBit(bytes, i, bits[i]);
    }

    return bytes;
}

public static bool[] ToBoolArray(byte[] bytes)
{
    var bitCount = bytes.Length * bitsPerByte;
    var bools = new bool[bitCount];
    for (int i = 0; i < bitCount; i++)
    {
        bools[i] = GetBit(bytes, i);
    }

    return bools;
}

这依赖于以下帮助代码:

private static bool GetBit(byte[] bytes, int bitNumber)
{
    var byteNumber = bitNumber / bitsPerByte;
    var bit = bitNumber % bitsPerByte;
    return GetBit(bytes[byteNumber], bit);
}

private static bool GetBit(byte byteValue, int bitNumber) => (byteValue >> bitNumber) % 2 > 0;

private static void SetBit(byte[] bytes, int bitNumber, bool value)
{
    var byteNumber = bitNumber / bitsPerByte;
    var bit = bitNumber % bitsPerByte;
    SetBit(ref bytes[byteNumber], bit, value);
}

private static void SetBit(ref byte byteValue, int bitNumber, bool value)
{
    var operand = (byte)(1 << bitNumber);
    if (value)
    {
        byteValue |= operand;
    }
    else
    {
        operand = (byte)~operand;
        byteValue &= operand;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 2017-10-02
    • 1970-01-01
    • 2016-11-17
    • 2012-10-11
    相关资源
    最近更新 更多