2009-05-18 26 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; 
    } 
} 
相关问题