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

时间:2011-06-14 16:58:55

标签: c# azure

我需要在Windows Azure中存储布尔数据。我想让这些空间尽可能小。我所拥有的是十五个字段,其值为false。

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

我有一个想法,我可以采取这些,将真和假转换为1和0,然后存储为类似1101的字符串。是否有一种简单的方法,我可以做这个编码,然后在获取数据时解码出来吗?请注意,字段名称都是不同的,因此我不能使用花哨的for循环来遍历字段名称。

11 个答案:

答案 0 :(得分:5)

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;
...

答案 1 :(得分:3)

我认为你甚至无法想象我是多么持怀疑态度,这会对任何方式,形状或形式有所帮助。 15个布尔人几乎没什么。

现在,如果您坚持沿着这条路走下去,最好的方法是将它们存储为单个int并使用&将其读出并|来编写它们回来了。

答案 2 :(得分:3)

考虑使用[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

答案 3 :(得分:2)

不要打扰。您正在使用布尔值,这些值已经大小(对于单个值),因为您可以得到(我相信1个字节)。而可能能够保存的少量空间不值得增加代码的复杂性,加上开发它所需的时间。


还有一些想法:想想你如何使用这样的结构。目前,如果您查看field_1并查看值true,则无需进一步了解实施情况以确定实际值。但是,假设您有以下字符串:“100101011011010”(或整数值19162,这将更有效)。 field_1是真的还是假的?它本身并不明显 - 您需要找到实现。当你需要在某个地方支持更多字段时会发生什么?通过坚持你所拥有的东西,你将为自己省去很多心痛。

答案 4 :(得分:2)

您可以使用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];

答案 5 :(得分:1)

将这些存储为字符将为每个值8或16位。我使用位移操作将它们打包成可用的最长无符号整数数组。

答案 6 :(得分:1)

答案 7 :(得分:0)

查看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变量。

答案 8 :(得分:0)

您可以使用int并使用xor http://www.dotnetperls.com/xor

来执行此操作

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

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

答案 9 :(得分:0)

你可以使用带有flags属性的Enum。你说你有15个字段。所以你可以尝试使用类似的东西 [标志] 枚举Fieldvals { Field1,Field2,.... }

请参阅http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx了解指南

答案 10 :(得分:0)

您可以将标记存储在整数值中。以下是一些辅助方法来实现:

// 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);
}