Frage

Ich versuche, eine Binärdatei mit der Binary Klasse zu lesen, und ich brauche es in als Blöcke von UInt32 zu lesen, und dann einige etwas tun usw. anschliessend verschoben wird.

Aber aus irgendeinem Grund etwas Reihenfolge umgekehrt wird, wenn ich die ReadUInt32 Methode verwenden.

Wenn ich zum Beispiel eine Datei, in der die ersten vier Bytes wie dies in hex aussehen, 0x12345678 landen sie so zusammen, nachdem er von ReadUInt32 gelesen werden. 0x78563412

Wenn ich das Readbytes verwenden (4) Verfahren, erhalte ich die erwartete Array:

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

Warum ist das? Ist es nur die Art und Weise .net uints im Speicher darstellt? Ist es das gleiche über die verschiedenen Plattformen (Ich bin mit 64-Bit-Windows 7, .net 3.5 SP1)?

War es hilfreich?

Lösung

Dies scheint ein endianness Thema. docs sagen ReadUint32 liest in Little-Endian so dass das erste Byte ist das niedrigstwertige so dass es auf die unterste Speicherstelle geht. Ihr Schriftsteller muss sein Big-Endian?

BinaryWriter.Write(UInt32) href="http://msdn.microsoft.com/en-us/library/d79ecdwh.aspx" rel="noreferrer"> sagt es Little-Endian schreibt auch. Ist Ihre binäre Datenquelle nicht Binary?

Im Grunde, was Sie tun müssen, um es zu beheben, ist dies:

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

Damit verschiebt sich das am wenigsten signifikante Byte bis 24 Bit, das zweite LSB bis 8 Bits, die 3. LSB um 8 Bits, und die vierte LSB (das MSB) bis 24 Bit. Dadurch wird in mehreren Bibliotheken abgedeckt.

Vielleicht BitConverter Verwendung wäre ein bisschen mehr klar sein:

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

Andere Tipps

Ja, hat dies mit, wie Sie Ihren Computer Baumärkten uints im Speicher zu tun. Es kann auf verschiedene Plattformen unterschiedlich sein, obwohl die meisten Desktop-Computer gleich sein sollten.

Dies ist Endian genannt - siehe wikipedia hier:

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

Schauen Sie in Jon Skeet MiscUtil Bibliothek für die Endian * Klassen, wie EndianBinaryReader und EndianBitConverter.

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

Jon Skeet geschrieben ein BitConverter mit konfigurierbaren Bytereihenfolge. Man könnte es nützlich finden.

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

Dies ist eine Frage der Plattform Endianess . Wenn Sie Daten aus einem Stream gelesen müssen Sie es entsprechend an die Endianess lesen es als geschrieben wurde. Wenn Sie die Daten in .NET erstellt, dann wird .Net es richtig gelesen.

Lesen Sie Generisches Binary und Binary Extensions , eine gute Möglichkeit, Generika zu handhaben Gießen der unmanaged Art und Weise.

Für VB.NET (sicheren Code nur, kann auch in C # erreicht werden) verwenden, wie folgt vor:

Imports System.IO Importe System.Runtime.CompilerServices Imports 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

Sie können nun die gleiche Funktionalität für BitConverter implementieren , für BinaryWriter etc.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top