Domanda

Sto cercando di leggere un file binario con la classe BinaryReader, e ho bisogno di leggerlo come blocchi di UInt32, e poi fare un po 'po' di spostamento ecc afterwords.

Ma, per qualche ragione ordine dei bit è invertito quando uso il metodo ReadUInt32.

Se io per esempio ho un file in cui i primi quattro byte sembra che questo in esadecimale, 0x12345678, finiscono in questo modo dopo essere stato letto da ReadUInt32:. 0x78563412

Se uso il metodo readBytes (4), ottengo l'array atteso:

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

Perché è questo? E 'solo il modo in cui .NET rappresenta uints in memoria? E 'lo stesso tra le diverse piattaforme (io sono in esecuzione a 64 bit di Windows 7, .net 3.5 SP1)?

È stato utile?

Soluzione

Questo sembra essere un endianness problema. La documentazione dicono ReadUint32 legge in little-endian in modo che il primo byte è il meno significativo così si va alla locazione di memoria più basso. Il tuo scrittore deve essere big-endian?

BinaryWriter.Write(UInt32) href="http://msdn.microsoft.com/en-us/library/d79ecdwh.aspx" rel="noreferrer"> dice che scrive little-endian troppo. È la vostra fonte di dati binari non BinaryWriter?

In sostanza ciò che è necessario fare per risolvere il problema è questo:

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

Questo sposta il byte meno significativo up 24 bit, il 2 ° LSB fino 8 bit, il 3 ° LSB giù 8 bit, e il 4 ° LSB (MSB) verso il basso 24 bit. Fare questo è coperto in diverse librerie.

Forse usando BitConverter sarebbe un po 'più chiaro:

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

Altri suggerimenti

Sì, questo ha a che fare con come il vostro computer Ferramenta uints in memoria. Può essere diverso su diverse piattaforme, anche se la maggior parte dei computer desktop dovrebbe essere lo stesso.

Questo è chiamato endianness - vedi wikipedia qui:

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

Se vuoi in biblioteca MiscUtil Jon Skeet per le classi Endian *, come EndianBinaryReader e EndianBitConverter.

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

di Jon Skeet scritto un BitConverter con configurabile endian-ness. Si potrebbe trovare utile.

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

Questo è un problema di endianess . Quando si leggono i dati da un flusso è necessario leggere di conseguenza alla endianess è stato scritto come. Se è stato creato i dati in .Net, quindi Net leggerà correttamente.

Generico BinaryReader e BinaryWriter estensioni , un ottimo modo per gestire generici gettando il modo in cui non gestito.

Per VB.NET (codice sicuro solo, può essere ottenuta anche in C #) utilizzare il seguente:

Imports System.IO Importazioni System.Runtime.CompilerServices Le importazioni 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

A questo punto è possibile implementare la stessa funzionalità per BitConverter , per BinaryWriter etc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top