1. 程式人生 > >將十六進位制字串轉為byte陣列

將十六進位制字串轉為byte陣列

需求是這樣有十六進位制字串要存為byte陣列

如string st = "0A000000",轉為byte後為 byte[0]=10,byte[1]=0,byte[2]=0,byte[3]=0   

因.net2.0可用Convert將十六進位制字串轉為byte有現成的就用吧。程式碼如下:

publicstaticbyte[] writebytes1(string sBytes)
        
{
            Stopwatch watch 
=new Stopwatch();
            watch.Reset();
            watch.Start();
            Debug.Assert(sBytes.Length 
%2==0"陣列長度錯");

            
int pos =0;
            
int len = (sBytes.Length /2);
            
byte[] b =newbyte[len];
            
int count = sBytes.Length;

            
for (int i =0; i < count; i +=2)
            
{
                b[pos] 
= Convert.ToByte(sBytes.Substring(i, 2), 16);
                pos
++
;
            }

            watch.Stop();
            Console.WriteLine(
"{0}:{1}""writebytes1", watch.Elapsed);
            
return b;
        }

但我覺得不夠快,且發現我傳的字串長度都是8的整數倍,於是就用Convert.ToInt32以8位長度來轉成uint32的數字再用BitConverter轉為byte陣列,但轉換後陣列內容與我的要求內容位置相返,所以再用Array.Reverse(Array)方法將陣列返轉,改了程式碼如下:

publicstatic
byte[] writebytes2(string sBytes)
        
{
            Stopwatch watch 
=new Stopwatch();
            watch.Reset();
            watch.Start();

            Debug.Assert(sBytes.Length 
%2==0"陣列長度錯");
            Debug.Assert(sBytes.Length 
%8==0"陣列長度不適合用於此方法");

            
int pos =0;
            
int len = (sBytes.Length /2);
            
byte[] b =newbyte[len];
            
int count = sBytes.Length;

      
byte[] bt;
            
for (int i =0; i < count; i +=8)
            
{
                bt 
= BitConverter.GetBytes(Convert.ToInt32(sBytes.Substring(i, 8), 16));
                Array.Reverse(bt);
                bt.CopyTo(b, pos);
                pos 
+=4;
            }


            watch.Stop();
            Console.WriteLine(
"{0}:{1}""writebytes2", watch.Elapsed);
            
return b;
        }

測了一下沒快多少,而且字串加長後反而更慢,馬上用Reflector看了一下發現是Array.Reverse的實現方法把速度拖下來了,沒辦法只能自已寫整型轉byte的方法不用BitConverter和Array.Reverse。程式碼如下:

publicstaticbyte[] writebytes3(string sBytes)
        
{
            Stopwatch watch 
=new Stopwatch();
            watch.Reset();
            watch.Start();

            Debug.Assert(sBytes.Length 
%2==0"陣列長度錯");
            Debug.Assert(sBytes.Length 
%8==0"陣列長度不適合用於此方法");

            
int pos =0;
            
int len = (sBytes.Length /2);
            
byte[] b =newbyte[len];
            
int count = sBytes.Length;

            
for (int i =0; i < count; i +=8)
            
{
                
ulong ui = Convert.ToUInt32(sBytes.Substring(i, 8), 16);
                b[pos] 
= (byte)((ui &0xFF000000>>24);
                b[pos 
+1= (byte)((ui &0x00FF0000>>16);
                b[pos 
+2= (byte)((ui &0x0000FF00>>8);
                b[pos 
+3= (byte)((ui &0x000000FF));

                pos 
+=4;
            }


            watch.Stop();
            Console.WriteLine(
"{0}:{1}""writebytes3", watch.Elapsed);
            
return b;
        }

測試了一下第三種方法只用了前兩種大約1/3的時間。(奇怪的是後來我又用ToUInt64取64位來寫同樣的方法,卻反而比用ToUInt32實現的方法慢,可惜無法瞭解底層API是如何實現Convert.ToUInt64,還請了解的能給我說說)

staticvoid Main(string[] args)
        {
            
string st ="1E041800050013000022A322232C2323303B5C2D22A322232C232330"+"1E041D00060018000022A322232C2323303B5B5265645D5C2D22A322232C232330"+"1E041E00070019000022A322232C2323302E30303B5C2D22A322232C2323302E3030"+"1E04230008001E000022A322232C2323302E30303B5B5265645D5C2D22A322232C2323302E3030"+"1E0435002A003000005F2D22A3222A20232C2323305F2D3B5C2D22A3222A20232C2323305F2D3B5F2D22A3222A20222D225F2D3B5F2D405F2D"+"1E042C0029002700005F2D2A20232C2323305F2D3B5C2D2A20232C2323305F2D3B5F2D2A20222D225F2D3B5F2D405F2D"+"1E043D002C003800005F2D22A3222A20232C2323302E30305F2D3B5C2D22A3222A20232C2323302E30305F2D3B5F2D22A3222A20222D223F3F5F2D3B5F2D405F2D"+"1E0434002B002F00005F2D2A20232C2323302E30305F2D3B5C2D2A20232C2323302E30305F2D3B5F2D2A20222D223F3F5F2D3B5F2D405F2D";

            
byte[] bt1 = writebytes1(st);
            
byte[] bt2 = writebytes2(st);
            
byte[] bt3 = writebytes3(st);

            
for (int i =0; i < bt1.Length; i++)
            {
                
if (bt1[i] != bt2[i] || bt1[i] != bt3[i] ) 
                {
                    Console.WriteLine(
"err");
                    
return;
                }
            }
            Console.WriteLine(
"ok");
        }