2010-11-11 16 views
4

J'ai un fichier binaire personnalisé que je veux lire dans mon programme C#.Puis-je utiliser C# Serialization pour lire un fichier binaire au format personnalisé?

Il existe plusieurs formats différents, d'abord MSB, LSB en premier et d'autres avec des variables dans différents ordres.

Actuellement, j'ai une classe qui lit le bon nombre d'octets, un à la fois.

C'est très lent et je cherche à améliorer les performances de toutes les façons possibles.

La sérialisation est-elle susceptible de mieux fonctionner? Si oui, est-ce possible avec le scénario que j'ai décidé? Est-il possible de personnaliser le BinaryFormatter pour le format big/little-endian?

Merci.

Répondre

2

Vous ne pouvez pas faire cela avec BinaryFormatter - il faudra s'attendre à des métadonnées/bourrages supplémentaires autour de l'objet. Vous auriez à lire manuellement soit à partir d'un Stream ou de manière similaire via un lecteur binaire.

Après avoir fait un code très similaire, je voudrais écrire mon propre lecteur qui se trouve au-dessus d'un cours d'eau, avec des méthodes telles que: ReadInt32LittleEndian, ReadInt32BigEndian (etc pour tout ce dont vous avez besoin) - et utilisez décalage (<</>>) pour assembler les octets. Mais important Je voudrais utiliser un tampon de sauvegarde pour réduire le nombre d'appels au flux sous-jacent (même avec un tampon, cela peut être inacceptable lent).

Laissez-moi vous référer à un code de protobuf-net qui fait cela ... en particulier ProtoReader, en prenant un exemple:

/// <summary> 
    /// Reads an unsigned 32-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64 
    /// </summary> 
    public uint ReadUInt32() 
    { 
     switch (wireType) 
     { 
      case WireType.Variant: 
       return ReadUInt32Variant(false); 
      case WireType.Fixed32: 
       if (available < 4) Ensure(4, true); 
       position += 4; 
       available -= 4; 
       return ((uint)ioBuffer[ioIndex++]) 
        | (((uint)ioBuffer[ioIndex++]) << 8) 
        | (((uint)ioBuffer[ioIndex++]) << 16) 
        | (((uint)ioBuffer[ioIndex++]) << 24); 
      case WireType.Fixed64: 
       ulong val = ReadUInt64(); 
       checked { return (uint)val; } 
      default: 
       throw CreateException(); 
     } 
    } 

(ici wireTypelargement agit comme indicater de boutisme etc, mais ce n'est pas important)

Regarder la mise en œuvre Fixed32:

  • Le Ensure fait en sorte que nous avons au moins 4 octets de plus dans notre tampon de support (aller chercher plus si nous voulons)
  • nous incrémenter des compteurs afin que nous puissions suivre notre position dans le tampon logique
  • on lit les données de le tampon

Si vous avez un lecteur pour votre format, la désérialisation devrait être beaucoup plus facile.

0

Non ça ne marchera pas. Eh bien, il pourrait, mais les frais généraux d'une transformation vont probablement tuer la performance.