將十六進位制字串轉為byte陣列
阿新 • • 發佈:2019-02-01
需求是這樣有十六進位制字串要存為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
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{
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");
}