2009-05-22 16 views
7

私はBinaryReaderクラスでバイナリファイルを読み込もうとしています。私はUInt32のブロックとして読み込み、後でビットシフトなどを行う必要があります。なぜBinaryReader.ReadUInt32()はビットパターンを反転させるのですか?

しかし、何らかの理由でReadUInt32メソッドを使用するとビット順序が逆になります。私は、例えば最初の4つのバイトが進、0x12345678にこのようなファイルがある場合は

は、彼らがReadUInt32によって読み取られた後、このように終わる:0x78563412

私は(4)メソッドReadBytesを使用している場合は、私が期待される配列を取得:

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

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

+0

あなたはそれをどのように修正したかを教えて、好奇心を鎮めることができますか? :) –

+1

もちろん:実際には、バイトオーダーがどのような方法であっても、platfroms(x64、x86)で一貫している限り、必要なビットを抽出することができます。シフト。私が見る限り、uintはReadUInt32で構築されたuintだけでなく、リトルエンディアンとして保存されるため、すべてが簡単になります。 –

答えて

8

をこれがendianness問題のようです。 The docs ReadUint32はリトルエンディアンで読み込みますので、最初のバイトは最下位になりますので、最も低いメモリ位置に移動します。あなたの作家はビッグエンディアンでなければなりませんか?

BinaryWriter.Write(UInt32)says it writesリトルエンディアンもあります。バイナリデータソースはBinaryWriterではありませんか?これは、24ビット、8ビット、8ビットダウン第三LSBまでの第二LSB、および最下位バイトをシフトアップ

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

基本的にあなたがそれを修正するために何をする必要があるかはこれです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); 
8

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

これは、エンディアンと呼ばれている - ここではウィキペディアを参照してください。

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

1

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

+0

lol 3ウィキペディアのリンクは1分以内です。それにはバッジがあるはずです! –

0

読むGeneric BinaryReader and BinaryWriter Extensions、管理されていない道を鋳造し、一般的な処理するための素晴らしい方法。

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 

あなたは今実装することができますBitConverterBinaryWriterなどと同じ機能です。

関連する問題