序列化数据太大了

时间:2012-10-21 19:23:30

标签: c# serialization protobuf-net

我为每个播放器服务器端序列化数据,它的大小约为128kb。我序列化[255,255] bool数组,这是映射的必要条件,我可以使用哪些替代方法,因为我听说gzip实际上会增加大小?

我听说过protobuf-net,但它没有记录,互联网上也没有例子。

3 个答案:

答案 0 :(得分:5)

我要做的第一件事就是:不将这些数据存储在bool[,]中 - 这是非常低效的,而且存储起来真的很痛苦。我会写一个包装器,将它变成一个平坦的byte[]

public sealed class BitGrid
{
    public BitGrid() {
        // 255 * 255 = 32 bytes per row, 255 rows
        bytes = new byte[8160];
    }
    public BitGrid(byte[] data)
    {
        if (data == null) throw new ArgumentNullException("data");
        if (data.Length != 8160) throw new ArgumentException("data");
        this.bytes = data;
    }

    readonly byte[] bytes;

    public bool this[byte x, byte y]
    {
        get
        {
            int xByte = x / 8, xBit = x % 8;
            byte val = bytes[(32 * y) + xByte];
            switch (xBit)
            {
                case 0: return (val & 1) != 0;
                case 1: return (val & 2) != 0;
                case 2: return (val & 4) != 0;
                case 3: return (val & 8) != 0;
                case 4: return (val & 16) != 0;
                case 5: return (val & 32) != 0;
                case 6: return (val & 64) != 0;
                case 7: return (val & 128) != 0;
            }
            throw new InvalidOperationException("oops!");
        }
        set
        {
            int xByte = x / 8, xBit = x % 8;
            int offset = (32 * y) + xByte;
            byte val = bytes[offset];
            if (value)
            {
                switch (xBit)
                {
                    case 0: val |= 1; break;
                    case 1: val |= 2; break;
                    case 2: val |= 4; break;
                    case 3: val |= 8; break;
                    case 4: val |= 16; break;
                    case 5: val |= 32; break;
                    case 6: val |= 64; break;
                    case 7: val |= 128; break;
                }
            }
            else
            {
                switch (xBit)
                {
                    case 0: val &= 254; break;
                    case 1: val &= 253; break;
                    case 2: val &= 251; break;
                    case 3: val &= 247; break;
                    case 4: val &= 239; break;
                    case 5: val &= 223; break;
                    case 6: val &= 191; break;
                    case 7: val &= 127; break;
                }
            }

            bytes[offset] = val;
        }
    }
    public byte[] ToArray()
    {
        return (byte[])bytes.Clone();
    }
}

然后序列化它,它只是:

byte[] data = grid.ToArray();
// store "data"

并反序列化,只是:

byte[] data = ...
grid = new BitGrid(data);

您可以使用byte[] / File.ReadAllBytes方法将File.WriteAllBytes保存到磁盘或从磁盘加载,或者如果您要存储其他数据,那么任何标准序列化程序都可以正常使用一个byte[]。这个数据总是8160字节 - 不到8k。

答案 1 :(得分:2)

您可以使用(一维)BitArray进行序列化。这将位打包成字节。

答案 2 :(得分:2)

如果您将布尔值表示为位并且序列化为二进制,则只有大约8千字节。

如果你需要的是文本,请使用base64序列化二进制文件,这将使其大​​约12千字节。

将二维数组展平为一维数组,并从中生成BitArray

示例:

bool[] bools = { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true };

BitArray bits = new BitArray(bools);
byte[] bytes = new byte[3];
bits.CopyTo(bytes, 0);

Console.WriteLine(BitConverter.ToString(bytes));
Console.WriteLine(Convert.ToBase64String(bytes));

Outut:

FF-FF-0F
//8P