2008-09-23 7 views
7

System.IO.BinaryReader lit les valeurs dans un format little-endian.Comment peut-on simplifier la conversion des octets d'ordre réseau à partir d'un BinaryReader?

J'ai une application C# connexion à une bibliothèque de réseau propriétaire sur le côté serveur. Le côté serveur envoie tout en bas dans l'ordre des octets du réseau, comme on peut s'y attendre, mais je trouve qu'il est difficile de gérer cela du côté client, en particulier pour les valeurs non signées.

UInt32 length = (UInt32)IPAddress.NetworkToHostOrder(reader.ReadInt32()); 

est la seule façon que je suis venu avec pour obtenir une valeur non signée correcte du flux, mais cela semble à la fois maladroit et laid, et je dois encore tester si cela va juste couper outre haute -ordonner les valeurs afin que je doive faire des choses amusantes BitConverter.

Y a-t-il un moyen de me passer de l'écriture d'un wrapper pour éviter ces vilaines conversions à chaque lecture? Il semble qu'il devrait y avoir une option endian-ness sur le lecteur pour rendre les choses plus simples, mais je n'ai rien trouvé.

+0

Le code d'origine fonctionne-t-il correctement lorsque les octets peuvent représenter un entier natif? –

+0

Il ne va pas aider, mais je créé un [connecter ticket] (https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=484149) pour BinaryReder/Writer pour soutenir bigEndian la boîte. Allez voter pour cela [ici] (https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=484149). –

Répondre

5

Il n'y a pas de convertisseur intégré. Voici mon emballage (comme vous pouvez le voir, je ne mis à exécution les fonctionnalités que je avais besoin, mais la structure est assez facile de changer à votre goût):

/// <summary> 
/// Utilities for reading big-endian files 
/// </summary> 
public class BigEndianReader 
{ 
    public BigEndianReader(BinaryReader baseReader) 
    { 
     mBaseReader = baseReader; 
    } 

    public short ReadInt16() 
    { 
     return BitConverter.ToInt16(ReadBigEndianBytes(2), 0); 
    } 

    public ushort ReadUInt16() 
    { 
     return BitConverter.ToUInt16(ReadBigEndianBytes(2), 0); 
    } 

    public uint ReadUInt32() 
    { 
     return BitConverter.ToUInt32(ReadBigEndianBytes(4), 0); 
    } 

    public byte[] ReadBigEndianBytes(int count) 
    { 
     byte[] bytes = new byte[count]; 
     for (int i = count - 1; i >= 0; i--) 
      bytes[i] = mBaseReader.ReadByte(); 

     return bytes; 
    } 

    public byte[] ReadBytes(int count) 
    { 
     return mBaseReader.ReadBytes(count); 
    } 

    public void Close() 
    { 
     mBaseReader.Close(); 
    } 

    public Stream BaseStream 
    { 
     get { return mBaseReader.BaseStream; } 
    } 

    private BinaryReader mBaseReader; 
} 

Fondamentalement, ReadBigEndianBytes-ce que le travail de base, ce qui est passé à un BitConverter. Il y aura un problème certain si vous lisez un grand nombre d'octets car cela entraînera une grande allocation de mémoire.

+0

Note: Array .Reverse() inversera l'ordre de votre tableau en place. –

1

J'ai construit une coutume BinaryReader pour gérer tout cela. Il est disponible en tant que part of my Nextem library. Il a également un moyen très simple de définir les structures binaires, ce qui, je pense, vous aidera ici - consultez les exemples.

Note: Il est seulement dans SVN en ce moment, mais très stable. Si vous avez des questions, écrivez-moi à cody_dot_brocious_at_gmail_dot_com.

+0

Merci. J'espérais en quelque sorte éviter de dépendre d'une dépendance supplémentaire de la bibliothèque, puisque tout cela devrait être assez petit et simple, mais je vais le garder à l'esprit. Heureux de voir la licence est sans ambiguïté, cependant. :) –

+0

Ah, je vois. Eh bien, j'espère que ça marchera pour vous si vous choisissez d'y aller. Et oui, je suis allé public domain juste pour cette raison - je veux que les gens puissent faire absolument tout ce qu'ils veulent avec, et les composants sont assez petits pour que les correctifs ne soient pas concernés :) –

Questions connexes