2009-05-22 6 views
7

BinaryReader 클래스를 사용하여 이진 파일을 읽으려고하는데 UInt32 블록으로 읽어야하고 이후에 약간의 비트 이동 등을해야합니다.왜 BinaryReader.ReadUInt32()가 비트 패턴을 뒤집습니까?

그러나 ReadUInt32 메서드를 사용할 때 어떤 이유로 비트 순서가 반대로됩니다.

예를 들어, 처음 4 바이트가 16 진수로 표시되는 파일 인 경우 0x12345678은 ReadUInt32 : 0x78563412에 의해 읽혀진 후 이렇게됩니다. 왜이

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

이다 : 나는의 readBytes를 사용하는 경우

(4) 방법은, 내가 예상되는 배열을 얻을? 그것은 단지 방법일까요? .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가 아닌가?

은 기본적으로 당신이 그것을 해결하기 위해해야 ​​할 일이 있습니다 :

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

예, 이것은 컴퓨터 하드웨어가 메모리에 uint를 저장하는 방법과 관련이 있습니다. 대부분의 데스크톱 컴퓨터가 동일해야하지만 플랫폼에 따라 다를 수 있습니다.

엔디안라고 - 위키 백과 여기 참조 :

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

1

이 플랫폼 Endianess의 문제입니다. 스트림에서 데이터를 읽을 때는 해당 스트림을 endianess에 맞게 읽어야합니다. .Net에서 데이터를 만든 경우 .Net은 올바르게 읽습니다.

+0

롤 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 

이제 구현할 수 있습니다 BitConverter, BinaryWriter 등의 동일한 기능.

관련 문제