8

BinaryReaderクラスでバイナリファイルを読み込もうとしていますが、UInt32のブロックとして読み込み、その後ビットシフトなどを行う必要があります。

しかし、ReadUInt32メソッドを使用すると、何らかの理由でビットの順序が逆になります。

たとえば、最初の4バイトが16進数で次のようになっているファイルがある場合、0x12345678ReadUInt32で読み取られた後は次のようになります0x78563412

ReadBytes(4)メソッドを使用すると、期待される配列が得られます。

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

どうしてこれなの?.netがメモリ内のuintを表す方法ですか?異なるプラットフォーム間で同じですか(64ビットのWindows 7、.net 3.5 sp1を実行しています)?

4

6 に答える 6

9

はい、これはコンピュータハードウェアがuintをメモリに保存する方法と関係があります。ほとんどのデスクトップコンピュータは同じである必要がありますが、プラットフォームによって異なる場合があります。

これはエンディアンと呼ばれます-ここのウィキペディアを参照してください:

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

于 2009-05-22T18:30:23.117 に答える
8

これはエンディアンの問題のようです。 ドキュメントによると、ReadUint32はリトルエンディアンで読み取るため、最初のバイトは最下位であるため、最下位のメモリ位置に移動します。あなたの作家はビッグエンディアンでなければなりませんか?

BinaryWriter.Write(UInt32) リトルエンディアンも書いていると言います。バイナリデータソースはBinaryWriterではありませんか?

基本的に、それを修正するために必要なことは次のとおりです。

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

これにより、最下位バイトが24ビット上にシフトされ、2番目のLSBが8ビット上にシフトされ、3番目のLSBが8ビット下にシフトされ、4番目のLSB(MSB)が24ビット下にシフトされます。これを行うことは、いくつかのライブラリでカバーされています。

おそらく、使用BitConverterする方がもう少し明確になります。

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);
于 2009-05-22T18:31:08.000 に答える
3

EndianBinaryReaderやEndianBitConverterなどのEndian*クラスについては、JonSkeetのMiscUtilライブラリを調べてください。

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

于 2009-05-22T18:33:39.400 に答える
2

Jon Skeetは、構成可能なエンディアンを備えたBitConverterを作成しました。あなたはそれが役に立つと思うかもしれません。

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

于 2009-05-22T18:33:45.733 に答える
1

これは、プラットフォームのエンディアンの問題です。ストリームからデータを読み取るときは、それが書き込まれたエンディアンに応じてデータを読み取る必要があります。.Netでデータを作成した場合、.Netはそれを正しく読み取ります。

于 2009-05-22T18:33:30.337 に答える
0

GenericBinaryReaderおよびBinaryWriterExtensionsをお読みください。これは、管理されていない方法で汎用キャストを処理するための優れた方法です。

VB.NET(安全なコードのみ、C#でも実現可能)の場合は、次を使用します。

System.IOをインポートしますSystem.Runtime.CompilerServicesをインポートします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

BitConverterこれで、、BinaryWriterなどに同じ機能を実装できます。

于 2010-07-18T01:04:53.043 に答える