2012-10-21 74 views
1

我序列化每個玩家服務器端的數據,大小約爲128kb。我序列化一個必須映射的[255,255] bools數組,我可以使用什麼替代方法,因爲我聽說gzip實際上會增加大小?序列化數據太大

我聽說過protobuf-net,但它沒有記錄,也沒有例子存在於互聯網上。

+1

不,GZipStream不會增加這個大小。你通過實際嘗試來抵抗FUD。 –

+0

@Hans很好,它*可以*,這取決於數據看起來如何隨機。假設一個很好的實現*斑點*數據是隨機的,你仍然有一個幀頭的開銷。一個不好的實現(沒有發現它是隨機的)可以做任何事情。 –

+1

你只是增加了更多的FUD,它仍然不會讓他嘗試它。 –

回答

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 
+0

雖然我會如何「扁平」數組?我將如何從base64重新創建它?這麼多的問題...... – Max0999

+0

@ Max0999:簡單地遍歷數組中的項目並將它們複製到一個新數組中以使其變平。使用'Convert.FromBase64String'從base64獲取字節。使用'新的BitArray(bytes)'來再次創建'BitArray',並且'CopyTo'方法將數據複製到'bool'數組中。 – Guffa

+0

我怎麼知道我需要多少字節? – Max0999

2

您可以使用(一維)BitArray進行序列化。這將這些比特打包成字節。

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

您可以使用File.ReadAllBytes/File.WriteAllBytes方法將byte[]保存/加載到磁盤或從磁盤加載,或者如果您有其他數據要存儲,則任何標準串行器將會w ork與byte[]罰款。該數據將始終爲8160字節 - 略低於8K。