2009-05-18 55 views
1

我正在解析一個二進制文件格式。它以一種自然適合c#的uint類型的方式編碼一個使用四個字節的整數。從字節數組中解開一個整數的習慣用c#是什麼?

什麼是實現這一功能的最C#/慣用方式:

uint ReadUint(byte[] buffer); 

假定緩衝區包含4個元素。完整的答案可能會考慮由文件中的小/大端假設引起的一些常見字節順序,並記錄它選擇解析的一個或多個字節順序。

回答

5

最基本的(但有點危險重新字節順序)爲:

return BitConverter.ToUInt32(buffer, 0); 

比高於其他,移位是好的(根據你自己的回覆) - 或者你可以使用Jon的EndianBitConverter in MiscUtil,該手柄翻譯。

(編輯)

小尾數位移版本我在protobuf網用的是漂亮的,很多相同的版本 - 我剛剛看了他們按升序排列,使用按位(不是數字)此外:

return ((uint)buffer[0]) 
     | (((uint)buffer[1]) << 8) 
     | (((uint)buffer[2]) << 16) 
     | (((uint)buffer[3]) << 24); 
1

正如有人在C來了,這是我目前如何實現這個功能:

static uint ReadLength(byte[] buffer) 
{ 
    uint result = ((uint) buffer[3]) << 24; 
    result |= ((uint) buffer[2]) << 16; 
    result |= ((uint) buffer[1]) << 8; 
    result |= buffer[offset]; 
    return result; 
} 

這解析維基百科聲稱在little-endian的方式設計了一個格式,就在i386上運行的.NET實現/ Vista的

+0

注意,按位|將比數字更簡單+ ...查看我的(更新)答案爲例。 – 2009-05-18 20:54:36

+0

爲什麼會|比+更簡單嗎? – 2009-05-18 20:58:34

+0

我的理解是,按位操作涉及的CPU比數學工作要少,因爲它只是應用了位掩碼。在「checked」上下文中可能會有額外的溢出檢查等(注意默認情況下C#是「unchecked」)。 – 2009-05-18 21:01:12

0

假設你想讀他們的數據流(如您的代碼會建議) 我會說,這是非常接近的事實上的標準方式:

MemoryStream ms = new MemoryStream(new byte[100]); 
BinaryReader br = new BinaryReader(ms); 
uint q = br.ReadUInt32(); 
0
byte[] ba = new byte[]{ 0x10, 0xFF, 0x11, 0x01 } ; 
var ui = BitConverter.ToUInt32(ba, 0); 

使用BitConverter Class

0

簡單的方法是

int val = System.BitConverter.ToInt32(buffer, 0); 

這使用當前系統的字節序,這可能會或可能不是你想要的是。

2

這個回覆實際上是一個擴展的評論(因此wiki)比較BitConverter的性能和bitshifting使用+ vs |;它只適用於微優化!

結果第一:

BitConverter: 972ms, chk=1855032704 
Bitwise: 740ms, chk=1855032704 
ReadLength: 1316ms, chk=1855032704 

或者結果,如果調整,以允許非零基礎偏移:

BitConverter: 905ms, chk=1855032704 
Bitwise: 1058ms, chk=1855032704 
ReadLength: 1244ms, chk=1855032704 

,代碼:

using System; 
using System.Diagnostics; 
static class Program 
{ 
    static void Main() 
    { 
     byte[] buffer = BitConverter.GetBytes((uint)123); 
     const int LOOP = 50000000; 
     uint chk = 0; 
     var watch = Stopwatch.StartNew(); 
     for (int i = 0; i < LOOP; i++) 
     { 
      chk += BitConverter.ToUInt32(buffer, 0); 
     } 
     watch.Stop(); 
     Console.WriteLine("BitConverter: " + watch.ElapsedMilliseconds 
      + "ms, chk=" + chk); 

     chk = 0; 
     watch = Stopwatch.StartNew(); 
     for (int i = 0; i < LOOP; i++) 
     { 
      chk += Bitwise(buffer); 
     } 
     watch.Stop(); 
     Console.WriteLine("Bitwise: " + watch.ElapsedMilliseconds 
      + "ms, chk=" + chk); 

     chk = 0; 
     watch = Stopwatch.StartNew(); 
     for (int i = 0; i < LOOP; i++) 
     { 
      chk += ReadLength(buffer); 
     } 
     watch.Stop(); 
     Console.WriteLine("ReadLength: " + watch.ElapsedMilliseconds 
      + "ms, chk=" + chk); 

     Console.ReadKey(); 
    } 
    static uint Bitwise(byte[] buffer) 
    { 
     return ((uint)buffer[0]) 
      | (((uint)buffer[1]) << 8) 
      | (((uint)buffer[2]) << 16) 
      | (((uint)buffer[3]) << 24); 
    } 
    static uint ReadLength(byte[] buffer) 
    { 
     uint result = ((uint)buffer[3]) << 24; 
     result += ((uint)buffer[2]) << 16; 
     result += ((uint)buffer[1]) << 8; 
     result += buffer[0]; 
     return result; 
    } 
} 
相關問題