2013-04-19 8 views
7

Próbuję odczytać plik binarny w języku C#, ale mam do czynienia z problemem. oświadczyłem, co następuje:Liczba szesnastkowa C#

public static readonly UInt32 NUMBER = 0XCAFEBABE; 

Następnie podczas czytania od samego początku pliku Pytam czytać pierwsze 4 bajty (już próbowałem różnych sposobów, ale jest to najprostszy):

UInt32 num = in_.ReadUInt32(); // in_ is a BinaryReader 

O ile wiem, 4 bajty to CA, FE, BA i BE (w języku heksadecymalnym), ale konwertują je na UInt Otrzymuję różne wartości. NUMER jest 3405691582, num jest 3199925962. Próbowałem też to zrobić:

byte[] f2 = {0xCA, 0xFE, 0xBA, 0xBE}; 

a wynik robi BitConverter.ToUInt32(new byte[]{0xCA, 0xFE, 0xBA, 0xBE},0) jest 3199925962.

może ktoś mi pomóc?

dzięki

+0

Czy próbowałeś 'byte [ ] f2 = {0xBE, 0xBA, 0xFE, 0xCA}; '? http://en.wikipedia.org/wiki/Endianness – I4V

+3

'CAFEBABE', to gorąca liczba: D – Nolonar

Odpowiedz

6

Wynika to z małej endianness urządzenia. Aby to sprawdzić, zobacz właściwość BitConverter.IsLittleEndian.

Zasadniczo liczby są przechowywane w odwrotnej kolejności bajtów, w porównaniu do ich zapisywania. Piszemy najbardziej znaczącą liczbę po lewej stronie, ale komputer (little endian) przechowuje znaczący bajt po lewej stronie co najmniej. Tak więc wynik, jaki otrzymujesz, jest naprawdę 0xBEBAFECA (3199925962 dziesiętny), a nie taki, jakiego oczekiwałeś.

można konwertować za pomocą przesunięcia bitowe operacje:

uint value = (f2[0] << 24) | (f2[1] << 16) | (f2[2] << 8) | f2[3]; 

Istnieje wiele sposobów konwersji, w tym IPAddress.NetworkToHostOrder jak I4V podkreślił f2.Reverse() itp

dla konkretnego kodu, wierzę, że byłaby najbardziej praktyczna:

uint num = (uint)IPAddress.NetworkToHostOrder(in_.ReadInt32()); 

to może spowodować niedomiar zmiennoprzecinkowy jednak, więc może to powodować problemy dowcip h a /checked compiler option or checked keyword (nie są też bardzo popularne).

Jeśli chcesz do czynienia z takimi sytuacjami i uzyskać jeszcze czystszy kod, zawinąć go w metodę rozszerzenia:

public static uint ReadUInt32NetworkOrder(this BinaryReader reader) 
{ 
    unchecked 
    { 
     return (uint)IPAddress.NetworkToHostOrder(reader.ReadInt32());  
    } 
} 
+0

' IPAddress.NetworkToHostOrder' – I4V

+0

@ I4V Ciągle zapominam o tej metodzie. Ktokolwiek umieścił to w klasie 'IPAddress' ... Niestety nie ma wersji UInt32 tej metody, więc będzie to wymagało dodatkowego manipulowania. – Thorarin

+0

'IPAddress.NetworkToHostOrder' konwertuje pomiędzy endiancyjnością adresów IP w pakietach protokołu IP (big-endian) i porządku hosta (little-endian na x86, ale może być typu big-endian na innych architekturach, takich jak ARM). Nie używaj tej funkcji, aby odwrócić endianness, ponieważ nie będzie działać na wielu platformach. – smead

3

to, co nazywa się byte order:

var result1 = BitConverter.ToUInt32(new byte[] { 0xCA, 0xFE, 0xBA, 0xBE }, 0); 
//3199925962 

var result2 = BitConverter.ToUInt32(new byte[] { 0xBE, 0xBA, 0xFE, 0xCA }, 0); 
//3405691582