2008-09-23 8 views
7

System.IO.BinaryReader lee valores en formato little-endian.¿Cómo se puede simplificar la conversión de orden de bytes de red desde un BinaryReader?

Tengo una aplicación C# que se conecta a una biblioteca de red propietaria en el lado del servidor. El lado del servidor envía todo en orden de bytes de red, como era de esperar, pero me parece que lidiar con esto en el lado del cliente es incómodo, particularmente para los valores sin firmar.

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

es la única manera que he llegado con conseguir un valor sin signo correcto de la corriente, pero esto parece tanto torpe y feo, y todavía tengo que probar si eso sólo va a recortar de alta -ordenar valores para que tenga que hacer cosas divertidas con BitConverter.

¿Hay alguna manera en la que me falte escribir una envoltura alrededor de todo para evitar estas feas conversiones en cada lectura? Parece que debería haber una opción de endianidad en el lector para simplificar cosas así, pero no he encontrado nada.

+0

¿El código original funciona correctamente cuando los bytes pueden representar un número entero nativo? –

+0

No será de ayuda ahora, pero creé un [boleto de conexión] (https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=484149) para BinaryReder/Writer para admitir Bigendian fuera de la caja. Vaya a votar aquí [aquí] (https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=484149). –

Respuesta

5

No hay un convertidor incorporado. Aquí está mi envoltorio (como se puede ver, lo único que implemente la funcionalidad que necesitaba pero la estructura es bastante fácil de cambiar a su gusto):

/// <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; 
} 

Básicamente, ReadBigEndianBytes el trabajo sucio, y esto se pasa a una BitConverter. Habrá un problema definido si lee una gran cantidad de bytes, ya que esto provocará una gran asignación de memoria.

+0

Nota: Matriz .Reverse() invertirá el orden de su matriz en su lugar. –

1

Creé un BinaryReader personalizado para manejar todo esto. Está disponible como part of my Nextem library. También tiene una forma muy fácil de definir estructuras binarias, lo que creo que te ayudará aquí; consulta los ejemplos.

Nota: Está solo en SVN en este momento, pero es muy estable. Si tiene alguna pregunta, envíeme un correo electrónico a cody_dot_brocious_at_gmail_dot_com.

+0

Gracias. Esperaba evitar la dependencia de una biblioteca adicional, ya que todo esto debería ser bastante pequeño y simple, pero lo tendré en cuenta. Aunque es agradable ver que la licencia no es ambigua. :) –

+0

Ah, ya veo. Bueno, espero que funcione para ti si eliges hacerlo. Y sí, me convertí en dominio público por ese mismo motivo: quiero que las personas puedan hacer absolutamente todo lo que quieran con él, y los componentes son lo suficientemente pequeños como para recuperar los parches: –

Cuestiones relacionadas