2012-10-21 5 views
1

Je sérialise les données pour chaque côté du serveur et sa taille est d'environ 128 Ko. Je sérialise un tableau [255,255] de booléens qui est un must pour la cartographie, quelles alternatives pourrais-je utiliser comme j'ai entendu gzip augmenterait réellement la taille?Sérialiser les données est trop grand

J'ai entendu parler de protobuf-net mais il n'est pas documenté et il n'existe aucun exemple sur internet.

+1

Non, GZipStream n'augmentera pas cette taille. Vous combattez FUD en l'essayant. –

+0

@Hans bien, il * peut * faire, en fonction de l'aspect aléatoire des données. En supposant une bonne implémentation qui * indique * que les données sont aléatoires, vous avez toujours le surcoût d'un en-tête de trame. Une mauvaise implémentation (qui n'indique pas que c'est aléatoire) pourrait faire à peu près n'importe quoi. –

+1

Vous ajoutez juste plus de FUD, ça ne le fera toujours pas l'essayer. –

Répondre

2

Si vous représentez les booléens sous forme de bits et de sérialisation en tant que binaire, cela ne représente que 8 kilo-octets.

Si vous avez besoin d'un texte, sérialisez le binaire en utilisant base64, ce qui le rendra environ 12 kilo-octets.

Aplatissez le tableau bidimensionnel en un tableau unidimensionnel et créez-en un BitArray.

Exemple:

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

Comment pourrais-je "aplatir" le tableau? comment pourrais-je le recréer à partir de base64? tant de questions ... – Max0999

+0

@ Max0999: Faites simplement une boucle sur les éléments du tableau et copiez-les dans un nouveau tableau pour les aplatir. Utilisez 'Convert.FromBase64String' pour récupérer les octets de base64. Utilisez 'newArrayArray (bytes)' pour faire un 'BitArray' à nouveau, et la méthode' CopyTo' pour copier les données dans un tableau 'bool'. – Guffa

+0

Comment savoir combien d'octets j'ai besoin? – Max0999

2

Vous pouvez utiliser un (unidimensionnel) BitArray pour la sérialisation. Cela emballe les bits en octets.

5

La première chose que je ferais serait: ne pas stocker ces données dans un bool[,] - qui est assez inefficace, et une vraie douleur pour stocker . Je voudrais écrire une enveloppe qu'il Cales à un byte[] plat:

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

Puis sérialiser, il est juste:

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

et désérialiser, il est juste:

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

Vous pouvez enregistrer/charger un byte[] sur/depuis le disque en utilisant les méthodes File.ReadAllBytes/File.WriteAllBytes, ou si vous avez d'autres données à stocker, tout sérialiseur standard ork bien avec un byte[]. Ces données seront toujours 8160 octets - un peu moins de 8k.