왜 BinaryReader.ReadUInt32()역방향의 비트 패턴을 가지고 있는가?
-
23-08-2019 - |
문제
내가 노력하고를 읽는 바이너리 파일이 BinaryReader 클래스고,필요해요 그것을 읽으로 블럭의 UInt32 고,다음 몇 가지 비트 시프트 등등.상품.
하지만,어떤 이유로 이 비문을 반전 사용할 때 내 ReadUInt32 방법입니다.
면 예를 들어 있는 파일의 첫번째 네 개의 바이트에서 다음과 같이 보입니다 육, 0x12345678
, 그들은 결국 같은 이 후로 읽 ReadUInt32: 0x78563412
.
내가 사용하는 경우에 ReadBytes(4)메소드,내가 예상 배열:
[0x00000000] 0x12 byte
[0x00000001] 0x34 byte
[0x00000002] 0x56 byte
[0x00000003] 0x78 byte
왜 그렇습니까?그것은 단지 방법입니다.net 나타냅 uints 에서 메모리가 있습니까?그것은 동일에 걸쳐 다양한 플랫폼(나는 실행하는 64 비트 윈도우 7,.net3.5sp1)?
해결책
이 될 것으로 보인 엔디안 문제입니다. 문서 말 ReadUint32 읽 little-endian 그래서 첫 번째 바이트는 적어도 중요 그래서 그것을 가장 낮은 메모리 위치에 있습니다.당신의 작가이어야 합 big-endian?
BinaryWriter.Write(UInt32)
그것을 말한다 기록 little-endian too.귀하의 바이너리 데이터를 원하지 않는 BinaryWriter?
기본적으로 필요가 무엇을 할 수정하는 것입니다:
uint a = 0x12345678;
uint b = ((a & 0x000000FF) << 24) + ((a & 0x0000FF00) << 8) + ((a & 0x00FF0000) >> 8) + ((a & 0xFF000000) >> 24);
이 교대를 최소한 바이트까지 24 비트,제 2LSB8 비트 3 데이터베이스를 최신으로 유지하려는 8 비트,그리고 4LSB(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);
다른 팁
예, 이것은 컴퓨터 하드웨어가 메모리에 저장하는 방법과 관련이 있습니다. 대부분의 데스크탑 컴퓨터는 동일해야하지만 플랫폼마다 다를 수 있습니다.
이것을 Endianness라고합니다. 여기 Wikipedia를 참조하십시오.
EndianbinaryReader 및 EndianbitConverter와 같은 Endian* 클래스에 대한 Jon Skeet의 Miscutil Library를 살펴보십시오.
Jon Skeet은 구성 가능한 Endian-sness가있는 비트 컨버터를 작성했습니다. 유용하다고 생각할 수 있습니다.
이것은 플랫폼의 문제입니다 endianess. 스트림에서 데이터를 읽으면 endianess에 따라 읽어 져야합니다. .NET에서 데이터를 만든 경우 .NET은 올바르게 읽습니다.
읽다 제네릭 바이린 리더 및 바이린 라이터 확장자, 관리되지 않는 방식으로 일반적인 캐스팅을 처리하는 좋은 방법.
vb.net의 경우 (안전한 코드 만 C#에서도 달성 할 수 있음) 다음을 사용하십시오.
Imports System.io Imports 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
이제 동일한 기능을 구현할 수 있습니다 BitConverter
, 을 위한 BinaryWriter
등.