2013-04-19 4 views
7

Я пытаюсь прочитать двоичный файл в C#, но перед вами стоит проблема. я заявил следующее:Шестнадцатеричные числа C#

public static readonly UInt32 NUMBER = 0XCAFEBABE; 

Тогда при чтении с самого начала файла я с просьбой прочитать первые 4 байта (уже пробовали разные способы, но это самый простой):

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

Хотя у меня есть 4 байта CA, FE, BA и BE (в шестнадцатеричном формате), в то время как они преобразуют их в UInt. Я получаю разные значения. НОМЕР 3405691582, Num является 3199925962. я также пытался сделать это:

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

и результат того, что BitConverter.ToUInt32(new byte[]{0xCA, 0xFE, 0xBA, 0xBE},0) является 3199925962.

может кто-нибудь мне помочь?

благодаря

+0

Вы пробовали 'Byte [ ] f2 = {0xBE, 0xBA, 0xFE, 0xCA}; '? http://en.wikipedia.org/wiki/Endianness – I4V

+3

'CAFEBABE', это горячий номер: D – Nolonar

ответ

6

Это из-за маленького endianness вашей машины. См. BitConverter.IsLittleEndian свойство, чтобы проверить это.

В принципе, цифры хранятся в порядке обратного байта по сравнению с тем, как вы их записывали. Мы пишем самое значительное число слева, но (маленький конец) ПК хранит наименьший значительный байт слева. Таким образом, результат, который вы получаете, действительно 0xBEBAFECA (3199925962 десятичный), а не то, что вы ожидали.

Вы можете конвертировать с помощью бит сдвига операции:

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

Есть еще много способов преобразования, в том числе IPAddress.NetworkToHostOrder, как I4V указывал, f2.Reverse() и т.д.

для вашего конкретного кода, я считаю, что это было бы наиболее практичным:

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

Это может привести к арифметическому недопущению, поэтому может возникнуть проблема с остроумием h a /checked compiler option or checked keyword (не очень распространены).

Если вы хотите иметь дело с этими ситуациями и получить еще более чистый код, завернуть его в метод расширения:

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

' IPAddress.NetworkToHostOrder' – I4V

+0

@ I4V Я все время забываю об этом методе. Кто бы это ни сказал в классе «IPAddress» ... К сожалению, нет версии UInt32 метода, так что для этого потребуется некоторое дополнительное упражнение. – Thorarin

+0

'IPAddress.NetworkToHostOrder' конвертирует между контентом IP-адресов в пакетах IP-протокола (big-endian) и хост-ордере (little-endian на x86, но может иметь большой смысл на других архитектурах, таких как ARM). Не входите в привычку использовать эту функцию, чтобы отменить утверждение, потому что она не будет работать кросс-платформенной. – smead

3

Вот что называется 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 
Смежные вопросы