在c#中存储布尔数据时如何节省空间

本文关键字:何节省 空间 数据 布尔 存储 | 更新日期: 2023-09-27 17:59:03

我需要在Windows Azure中存储布尔数据。我想让这些东西占据的空间尽可能小。我有大约十五个字段,它们的值是真是假。

field_1 = true;
field_2 = true;
field_a = false;
field_xx = true;

我有一个想法,我可以接受这些,将真值和假值转换为1和0,然后存储为类似1101的字符串。有没有一种简单的方法可以让我进行编码,然后在取出数据时打开编码?请注意,字段名称都是不同的,所以我不能使用花哨的for循环来遍历字段名称。

在c#中存储布尔数据时如何节省空间

int bits = (field_1 ? 1 : 0) | (field_2 ? 2 : 0) | (field_3 ? 4 : 0) | (field_4 ? 8 : 0) | ...
field_1 = (bits & 1) != 0;
field_2 = (bits & 2) != 0;
field_3 = (bits & 4) != 0;
field_4 = (bits & 8) != 0;
...

我想你甚至无法想象我有多怀疑这会在任何方面、形状或形式上有所帮助。15个布尔值根本不算什么。

现在,如果你坚持走这条路,最好的方法是将它们存储为一个单独的int,并使用&读取它们,使用|将它们写回。

您可以使用BitArray将布尔值打包到int:中

BitArray b = new BitArray(new bool[] { field_1, field_2, ..., field_xy });
int[] buffer = new int[1];
b.CopyTo(buffer, 0);
int data = buffer[0];

可以使用byteint阵列。byte最多可容纳8个布尔值,int最多可容纳32个布尔值。要容纳多达16个布尔值,可以使用具有两个字节的字节数组,也可以使用单个int,这取决于数组的开销或int中未使用的位是否占用更多空间。您还可以使用BitConverter类将两字节数组转换为short

要返回布尔值,您可以从byteint:的数组创建一个BitArray

BitArray b = new BitArray(new int[] { data });
field_1 = b[0];
field_2 = b[1];
...
field_xy = b[14];

考虑一个具有[Flags]属性的枚举

[Flags]
public enum Values
{
  Field1 = 1,
  Field2 = 2,
  Field3 = 4,
  Field4 = 8
}    
Values obj = Field1 | Field2;
obj.HasValue(Field1); //true
obj.HasValue(Field3); //false
int storage = (int)obj;// 3

将它们存储为字符,每个值需要8或16位。我会使用位移位操作将它们打包到可用的最长无符号整数的数组中。

有一篇关于这方面的好文章:http://blog.millermedeiros.com/2010/12/using-integers-to-store-multiple-boolean-values/

不用麻烦。您使用的是布尔值,它已经尽可能小了(对于单个值)(我相信是1字节)。您可能能够节省的少量空间不值得增加代码的复杂性,再加上开发代码所需的时间。


还有一些想法:想想你会如何使用这样一个结构。目前,如果您查看field_1并看到值true,则不必进一步查看实现来计算实际值。但是,假设您有以下字符串:"100101011011010"(或者19162的整数值,这会更有效)。field_1是真的,还是假的?它本质上并不明显——你需要去寻找实现。当你需要支持更多的领域时,会发生什么?坚持你所拥有的,你会省去很多心痛。

看看BitArray类,它应该能满足您的需要。

示例:

BitArray bits = new BitArray
(
    new bool[]
    {
        false, true, false, false, true, 
        false, true, false, true, false,
        false, true, false, true, false
    }
);
short values = 0;
for( int index = 0; index < bits.Length; index++ )
{
    if( bits[ index ] )
        values |= ( short )( values | ( 1 << index ) ); 
}
Console.WriteLine( Convert.ToString( values, 2 ) );

现在,在一个16位字段中存储了15个bool变量。

您可以使用int和xorhttp://www.dotnetperls.com/xor

大约15年前,我看到了一个这样做的项目。但它最终在系统中限制了32个角色(它使用了一个32位的数字)。该产品目前不存在:)

所以不要这样做,将值存储在数组或单独的字段中。

您可以将Enum与flags属性一起使用。你说你有15个字段。所以你可以尝试使用[标志]enum字段{字段1、字段2。。。。}

看看http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx对于指南

您可以将标志存储在整数值中以下是一些帮助实现这一点的方法:

// Sets the given bit position in the UInt32 to the specified boolean value 
public static UInt32 Set(UInt32 u, int position, bool newBitValue)
{
    UInt32 mask = (UInt32)(1 << position);
    if (newBitValue)
        return (u | mask)
    else
        return (u & ~mask);
}
// Gets a bit value from the supplied UInt32
public static bool Get(UInt32 u, int position)
{
    return ((u & (UInt32)(1 << position)) != 0);
}