public static string ByteArrayToString(byte[] ba){StringBuilder hex = new StringBuilder(ba.Length * 2);foreach (byte b in ba)hex.AppendFormat("{0:x2}", b);return hex.ToString();}
或:
public static string ByteArrayToString(byte[] ba){return BitConverter.ToString(ba).Replace("-","");}
public static class ByteExtensions{public static string ToHexString(this byte[] ba){StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba){hex.AppendFormat("{0:x2}", b);}return hex.ToString();}}
public static string ToHexString(byte[] data) {byte b;int i, j, k;int l = data.Length;char[] r = new char[l * 2];for (i = 0, j = 0; i < l; ++i) {b = data[i];k = b >> 4;r[j++] = (char)(k > 9 ? k + 0x37 : k + 0x30);k = b & 15;r[j++] = (char)(k > 9 ? k + 0x37 : k + 0x30);}return new string(r);}
public static string ByteArrayToString(byte[] ba){// Concatenate the bytes into one long stringreturn ba.Aggregate(new StringBuilder(32),(sb, b) => sb.Append(b.ToString("X2"))).ToString();}
public static string ByteArrayToString(byte[] ba){StringBuilder hex = new StringBuilder(ba.Length * 2);
for(int i=0; i < ba.Length; i++) // <-- Use for loop is faster than foreachhex.Append(ba[i].ToString("X2")); // <-- ToString is faster than AppendFormat
return hex.ToString();}
Public Function BufToHex(ByVal buf() As Byte) As StringDim sB As New System.Text.StringBuilderFor i As Integer = 0 To buf.Length - 1sB.Append(buf(i).ToString("x2"))Next iReturn sB.ToStringEnd Function
Give me that string:04c63f7842740c77e545bb0b2ade90b384f119f6ab57b680b7aa575a2f40939f
Time to parse 100,000 times: 50.4192 msResult as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-57-B6-80-B7-AA-57-5A-2F-40-93-9F
Accepted answer: (StringToByteArray)Time to parse 100000 times: 233.1264msResult as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-57-B6-80-B7-AA-57-5A-2F-40-93-9F
With Mono's implementation:Time to parse 100000 times: 777.2544msResult as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-57-B6-80-B7-AA-57-5A-2F-40-93-9F
With SoapHexBinary:Time to parse 100000 times: 845.1456msResult as base64: BMY/eEJ0DHflRbsLKt6Qs4TxGfarV7aAt6pXWi9Ak58=BitConverter'd: 04-C6-3F-78-42-74-0C-77-E5-45-BB-0B-2A-DE-90-B3-84-F1-19-F6-AB-57-B6-80-B7-AA-57-5A-2F-40-93-9F
Base64和BitConver'行用于测试正确性。请注意,它们是相等的。
实施:
public static byte[] ToByteArrayFromHex(string hexString){if (hexString.Length % 2 != 0) throw new ArgumentException("String must have an even length");var array = new byte[hexString.Length / 2];for (int i = 0; i < hexString.Length; i += 2){array[i/2] = ByteFromTwoChars(hexString[i], hexString[i + 1]);}return array;}
private static byte ByteFromTwoChars(char p, char p_2){byte ret;if (p <= '9' && p >= '0'){ret = (byte) ((p - '0') << 4);}else if (p <= 'f' && p >= 'a'){ret = (byte) ((p - 'a' + 10) << 4);}else if (p <= 'F' && p >= 'A'){ret = (byte) ((p - 'A' + 10) << 4);} else throw new ArgumentException("Char is not a hex digit: " + p,"p");
if (p_2 <= '9' && p_2 >= '0'){ret |= (byte) ((p_2 - '0'));}else if (p_2 <= 'f' && p_2 >= 'a'){ret |= (byte) ((p_2 - 'a' + 10));}else if (p_2 <= 'F' && p_2 >= 'A'){ret |= (byte) ((p_2 - 'A' + 10));} else throw new ArgumentException("Char is not a hex digit: " + p_2, "p_2");
return ret;}
public static byte[] StrToByteArray(string str){Dictionary<string, byte> hexindex = new Dictionary<string, byte>();for (byte i = 0; i < 255; i++)hexindex.Add(i.ToString("X2"), i);
List<byte> hexres = new List<byte>();for (int i = 0; i < str.Length; i += 2)hexres.Add(hexindex[str.Substring(i, 2)]);
return hexres.ToArray();}
public static string ByteArrayToString2(byte[] ba){char[] c = new char[ba.Length * 2];for( int i = 0; i < ba.Length * 2; ++i){byte b = (byte)((ba[i>>1] >> 4*((i&1)^1)) & 0xF);c[i] = (char)(55 + b + (((b-10)>>31)&-7));}return new string( c );}
颓废的linq-with bit黑客版本:
public static string ByteArrayToString(byte[] ba){return string.Concat( ba.SelectMany( b => new int[] { b >> 4, b & 0xF }).Select( b => (char)(55 + b + (((b-10)>>31)&-7))) );}
反向:
public static byte[] HexStringToByteArray( string s ){byte[] ab = new byte[s.Length>>1];for( int i = 0; i < s.Length; i++ ){int b = s[i];b = (b - '0') + ((('9' - b)>>31)&-7);ab[i>>1] |= (byte)(b << 4*((i&1)^1));}return ab;}
<Extension()>Public Function FromHexToByteArray(hex As String) As Byte()hex = If(hex, String.Empty)If hex.Length Mod 2 = 1 Then hex = "0" & hexReturn Enumerable.Range(0, hex.Length \ 2).Select(Function(i) Convert.ToByte(hex.Substring(i * 2, 2), 16)).ToArrayEnd Function
<Extension()>Public Function ToHexString(bytes As IEnumerable(Of Byte)) As StringReturn String.Concat(bytes.Select(Function(b) b.ToString("X2")))End Function
public static String ToHex (byte[] data){int dataLength = data.Length;// pre-create the stringbuilder using the length of the data * 2, precisely enoughStringBuilder sb = new StringBuilder (dataLength * 2);for (int i = 0; i < dataLength; i++) {int b = data [i];
// check using calculation over bits to see if first tuple is a letter// isLetter is zero if it is a digit, 1 if it is a letterint isLetter = (b >> 7) & ((b >> 6) | (b >> 5)) & 1;
// calculate the code using a multiplication to make up the difference between// a digit character and an alphanumerical characterint code = '0' + ((b >> 4) & 0xF) + isLetter * ('A' - '9' - 1);// now append the result, after casting the code point to a charactersb.Append ((Char)code);
// do the same with the lower (less significant) tupleisLetter = (b >> 3) & ((b >> 2) | (b >> 1)) & 1;code = '0' + (b & 0xF) + isLetter * ('A' - '9' - 1);sb.Append ((Char)code);}return sb.ToString ();}
public static byte[] FromHex (String hex){
// pre-create the arrayint resultLength = hex.Length / 2;byte[] result = new byte[resultLength];// set validity = 0 (0 = valid, anything else is not valid)int validity = 0;int c, isLetter, value, validDigitStruct, validDigit, validLetterStruct, validLetter;for (int i = 0, hexOffset = 0; i < resultLength; i++, hexOffset += 2) {c = hex [hexOffset];
// check using calculation over bits to see if first char is a letter// isLetter is zero if it is a digit, 1 if it is a letter (upper & lowercase)isLetter = (c >> 6) & 1;
// calculate the tuple value using a multiplication to make up the difference between// a digit character and an alphanumerical character// minus 1 for the fact that the letters are not zero basedvalue = ((c & 0xF) + isLetter * (-1 + 10)) << 4;
// check validity of all the other bitsvalidity |= c >> 7; // changed to >>, maybe not OK, use UInt?
validDigitStruct = (c & 0x30) ^ 0x30;validDigit = ((c & 0x8) >> 3) * (c & 0x6);validity |= (isLetter ^ 1) * (validDigitStruct | validDigit);
validLetterStruct = c & 0x18;validLetter = (((c - 1) & 0x4) >> 2) * ((c - 1) & 0x2);validity |= isLetter * (validLetterStruct | validLetter);
// do the same with the lower (less significant) tuplec = hex [hexOffset + 1];isLetter = (c >> 6) & 1;value ^= (c & 0xF) + isLetter * (-1 + 10);result [i] = (byte)value;
// check validity of all the other bitsvalidity |= c >> 7; // changed to >>, maybe not OK, use UInt?
validDigitStruct = (c & 0x30) ^ 0x30;validDigit = ((c & 0x8) >> 3) * (c & 0x6);validity |= (isLetter ^ 1) * (validDigitStruct | validDigit);
validLetterStruct = c & 0x18;validLetter = (((c - 1) & 0x4) >> 2) * ((c - 1) & 0x2);validity |= isLetter * (validLetterStruct | validLetter);}
if (validity != 0) {throw new ArgumentException ("Hexadecimal encoding incorrect for input " + hex);}
return result;}
input length: 10,000,000 bytesruns: 100average elapsed time per run:V1 = 136.4msV2 = 104.5msV3 = 22.0msV4 = 9.9msV5_1 = 10.2msV5_2 = 9.0msV5_3 = 9.3msV6 = 18.3msV7 = 9.8msV8 = 8.8msV9 = 10.2msV10 = 19.0msV11 = 12.2msV12 = 27.4msV13 = 21.8msV14 = 12.0msV15 = 14.9msV16 = 15.3msV17 = 9.5msV18 got excluded from this test, because it was very slow when using very long stringV19 = 222.8msV20 = 66.0msV21 = 15.4ms
V1 average ticks per run: 1363529.4V2 is more fast than V1 by: 1.3 times (ticks ratio)V3 is more fast than V1 by: 6.2 times (ticks ratio)V4 is more fast than V1 by: 13.8 times (ticks ratio)V5_1 is more fast than V1 by: 13.3 times (ticks ratio)V5_2 is more fast than V1 by: 15.2 times (ticks ratio)V5_3 is more fast than V1 by: 14.8 times (ticks ratio)V6 is more fast than V1 by: 7.4 times (ticks ratio)V7 is more fast than V1 by: 13.9 times (ticks ratio)V8 is more fast than V1 by: 15.4 times (ticks ratio)V9 is more fast than V1 by: 13.4 times (ticks ratio)V10 is more fast than V1 by: 7.2 times (ticks ratio)V11 is more fast than V1 by: 11.1 times (ticks ratio)V12 is more fast than V1 by: 5.0 times (ticks ratio)V13 is more fast than V1 by: 6.3 times (ticks ratio)V14 is more fast than V1 by: 11.4 times (ticks ratio)V15 is more fast than V1 by: 9.2 times (ticks ratio)V16 is more fast than V1 by: 8.9 times (ticks ratio)V17 is more fast than V1 by: 14.4 times (ticks ratio)V19 is more SLOW than V1 by: 1.6 times (ticks ratio)V20 is more fast than V1 by: 2.1 times (ticks ratio)V21 is more fast than V1 by: 8.9 times (ticks ratio)
长弦的V18性能
V18 took long time at the previous test,so let's decrease length for it:input length: 1,000,000 bytesruns: 100average elapsed time per run: V1 = 14.1ms , V18 = 146.7msV1 average ticks per run: 140630.3V18 is more SLOW than V1 by: 10.4 times (ticks ratio)
短弦的性能
input length: 100 byteruns: 1,000,000V1 average ticks per run: 14.6V2 is more fast than V1 by: 1.4 times (ticks ratio)V3 is more fast than V1 by: 5.9 times (ticks ratio)V4 is more fast than V1 by: 15.7 times (ticks ratio)V5_1 is more fast than V1 by: 15.1 times (ticks ratio)V5_2 is more fast than V1 by: 18.4 times (ticks ratio)V5_3 is more fast than V1 by: 16.3 times (ticks ratio)V6 is more fast than V1 by: 5.3 times (ticks ratio)V7 is more fast than V1 by: 15.7 times (ticks ratio)V8 is more fast than V1 by: 18.0 times (ticks ratio)V9 is more fast than V1 by: 15.5 times (ticks ratio)V10 is more fast than V1 by: 7.8 times (ticks ratio)V11 is more fast than V1 by: 12.4 times (ticks ratio)V12 is more fast than V1 by: 5.3 times (ticks ratio)V13 is more fast than V1 by: 5.2 times (ticks ratio)V14 is more fast than V1 by: 13.4 times (ticks ratio)V15 is more fast than V1 by: 9.9 times (ticks ratio)V16 is more fast than V1 by: 9.2 times (ticks ratio)V17 is more fast than V1 by: 16.2 times (ticks ratio)V18 is more fast than V1 by: 1.1 times (ticks ratio)V19 is more SLOW than V1 by: 1.6 times (ticks ratio)V20 is more fast than V1 by: 1.9 times (ticks ratio)V21 is more fast than V1 by: 11.4 times (ticks ratio)