在網絡通信中常利用字節數組(byte[]) 收發數據,是因為計算機中只能識別0/1編碼,一個字節Byte 占8 位 bit(0/1編碼),非常方便的表達二進制bit流 的傳輸序列。而網絡抓包或收發數據包檢測分析時常利用16進制格式顯示,因為二進制書寫較長,難以記憶,而每4個二進制位對應1個16進制位,兩位16進制的數剛好表達一個字節(8位),比較直觀。
二進制和16進制之間具有對應關系見下表
例如:180 對應的二進制為:10110100 ,由上表得到 1011 = B, 0100=4 ,所有180的16進制表示為:B4
例如下圖:字符串ASCII編碼后對應的16進制表示:
在C#中有一個數據基本類型byte表示范圍0到255,經常需要進行字符串轉16進制、及16進制與byte或byte[]的轉化。
1:單個byte轉16進制字符串
byte _byte = 97; string result= Convert.ToString(_byte, 16);// result="61"
不足2位補零:例如換行符:\n 對應ASCII表的10進制為10.
byte _byte = 10; string result= Convert.ToString(_byte, 16); // a result = _byte.ToString("X2"); //0A 或小寫 .ToString("x2") 變成0a
2:byte[]轉16進制字符串
有了上面的情形1,byte數組轉16進制字符串,只需要循環逐個轉換,然后拼接所有字符串返回結果即可,代碼如下:
/// <summary> /// 字節數組轉16進制字符串:空格分隔 /// </summary> /// <param name="byteDatas"></param> /// <returns></returns> public static string ToHexStrFromByte(this byte[] byteDatas) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < byteDatas.Length; i++) { builder.Append(string.Format("{0:X2} ", byteDatas[i])); } return builder.ToString().Trim(); }
3:普通字符串轉16進制格式字符串
有了使用1和2的例子,只需先將字符串根據編碼規則轉成byte[] ,再遍歷byte[]各元素轉成string,最后做拼接即可。代碼如下:
/// <summary> /// 用指定編碼將給定的字符串轉16進制格式字符串 /// </summary> /// <param name="plainString">待轉換的字符串</param> /// <param name="encode">編碼規則</param> /// <returns></returns> public static string ToHexString(this string plainString, Encoding encode) { byte[] byteDatas = encode.GetBytes(plainString); return ToHexStrFromByte(byteDatas); }
方式2:
public static string ToHexString(this string plainString, Encoding encode) { return BitConverter.ToString(encode.GetBytes(plainString)).Replace("-", " "); }
用法: string test= "%01#abcABCR00051**\r\n".ToHexString(Encoding.ASCII);
結果:25 30 31 23 61 62 63 41 42 43 52 30 30 30 35 31 2A 2A 0D 0A
4:16進制字符串格式轉化byte數組
下面的轉化假定傳過來的是類似“25 30 31 23 61 62 63 41 42 43 52 30 30 ”這樣的格式。
/// <summary> /// 16進制格式字符串轉字節數組 /// </summary> /// <param name="hexString"></param> /// <returns></returns> public static byte[] ToBytesFromHexString(this string hexString) { //以 ' ' 分割字符串,並去掉空字符 string[] chars = hexString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); byte[] returnBytes = new byte[chars.Length]; //逐個字符變為16進制字節數據 for (int i = 0; i < chars.Length; i++) { returnBytes[i] = Convert.ToByte(chars[i], 16); } return returnBytes; }
在使用1中利用了Convert.ToString(byte,16) 轉化成16進制,反過來,16進制的字符可以利用Convert.ToByte(string, 16)轉化成byte
5:16進制字符串格式轉化成可閱讀文本
基於使用4,可得到下面的方法
/// <summary> /// 16進制格式字符串轉普通文本 /// </summary> /// <param name="hexString">16進制格式字符串</param> /// <param name="encode">編碼規則</param> /// <returns></returns> public static string ToStringFromHexString(this string hexString, Encoding encode) { byte[] _bytes = ToBytesFromHexString(hexString); return encode.GetString(_bytes); }
使用: string hexStr= "%01#abcABCR00051**\r\n".ToHexString(Encoding.ASCII);
//25 30 31 23 61 62 63 41 42 43 52 30 30 30 35 31 2A 2A 0D 0A
string normalStr = hexStr.ToStringFromHexString(Encoding.ASCII);