Pregunta

Estoy tratando de leer un archivo binario con la clase BinaryReader, y necesito leerlo en forma de bloques de UInt32, y luego hacer algún desplazamiento de bits etc. epílogos.

Pero, por alguna razón orden de los bits se invierte cuando se utiliza el método ReadUInt32.

Si yo por ejemplo tengo un archivo en el que los primeros cuatro bytes es la siguiente con hexagonal, 0x12345678, que terminar así después de ser leído por ReadUInt32:. 0x78563412

Si utilizo el readBytes (4) método, consigo la matriz esperada:

[0x00000000]    0x12    byte
[0x00000001]    0x34    byte
[0x00000002]    0x56    byte
[0x00000003]    0x78    byte

¿Por qué es esto? ¿Es sólo la forma en .NET representa uints en la memoria? ¿Es lo mismo a través de las diferentes plataformas (estoy corriendo Windows de 64 bits 7, .NET 3.5 SP1)?

¿Fue útil?

Solución

Esto parece ser un href="http://en.wikipedia.org/wiki/Endianness" rel="noreferrer"> endianness tema Los documentos dicen ReadUint32 lee en ascendente hacia la izquierda por lo que el primer byte es el menos significativo por lo que pasa a la posición de memoria más bajo. Su escritor debe ser grande-endian?

BinaryWriter.Write(UInt32) href="http://msdn.microsoft.com/en-us/library/d79ecdwh.aspx" rel="noreferrer"> dice que escribe ascendente hacia la izquierda también. No se BinaryWriter su fuente de datos binarios?

En esencia lo que hay que hacer para solucionarlo es la siguiente:

uint a = 0x12345678;
uint b = ((a & 0x000000FF) << 24) + ((a & 0x0000FF00) << 8) + ((a & 0x00FF0000) >> 8) + ((a & 0xFF000000) >> 24);

Esto desplaza el byte menos significativo de hasta 24 bits, el segundo LSB hasta 8 bits, la tercera LSB abajo 8 bits, y el cuarto LSB (MSB) hasta 24 bits. Hacer esto se cubre en varias bibliotecas.

Tal vez usando BitConverter sería un poco más claro:

uint a = 0x12345678;
byte[] bytes = BitConverter.GetBytes(a);
// Swap byte order
uint b = BitConverter.ToUInt32(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0);

Otros consejos

Sí, esto tiene que ver con cómo su equipo se almacena en la memoria de hardware uints. Puede ser diferente en diferentes plataformas, aunque la mayoría de las computadoras de escritorio deben ser los mismos.

Esto se llama endianness - véase Wikipedia aquí:

http://en.wikipedia.org/wiki/Endian

Mira en la biblioteca MiscUtil de Jon Skeet para las clases de Endian *, como EndianBinaryReader y EndianBitConverter.

http://www.yoda.arachsys.com/csharp/miscutil/

Jon Skeet escrito un BitConverter con endian-ness configurable. Puede que le resulte útil.

http://www.yoda.arachsys.com/csharp/miscutil/

Este es un tema de la plataforma endianess . Cuando uno lee los datos de una corriente que debe leer en consecuencia a la endianess se escribe como. Si ha creado los datos de .Net, a continuación, .Net lo leerá correctamente.

Genérico BinaryReader y BinaryWriter Extensiones , una gran manera de manejar genérica echando el camino no administrado.

En VB.NET (código de seguridad solamente, también se puede lograr en C #) utilizar el siguiente:

Imports System.IO importaciones System.Runtime.CompilerServices Las importaciones System.Runtime.InteropServices

<HideModuleName()>
Public Module BinaryReaderExtensions

 <Extension()>
 Public Function Read(Of T As Structure)(br As BinaryReader) As T
  Dim bytes = br.ReadBytes(Marshal.SizeOf(GetType(T)))
  Dim handle = GCHandle.Alloc(bytes, GCHandleType.Pinned)
  Return Marshal.PtrToStructure(handle.AddrOfPinnedObject, GetType(T))
 End Function

 <Extension()>
 Public Function ReadReverse(Of T As Structure)(br As BinaryReader) As T
  Dim bytes = br.ReadBytes(Marshal.SizeOf(GetType(T))).Reverse.ToArray
  Dim handle = GCHandle.Alloc(bytes, GCHandleType.Pinned)
  Return Marshal.PtrToStructure(handle.AddrOfPinnedObject, GetType(T))
 End Function

End Module

Ahora puede aplicar la misma funcionalidad para BitConverter , para BinaryWriter etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top