Байт [] в шестнадцатеричную строку
Как мне конвертировать byte[]
к string
? Каждый раз, когда я пытаюсь это сделать, я получаю
System.Byte[]
вместо значения.
Кроме того, как я могу получить значение в шестнадцатеричном, а не десятичном?
19 ответов
Для этого есть встроенный метод:
byte[] data = { 1, 2, 4, 8, 16, 32 };
string hex = BitConverter.ToString(data);
Результат: 01-02-04-08-10-20
Если вы хотите это без черточек, просто удалите их:
string hex = BitConverter.ToString(data).Replace("-", string.Empty);
Результат: 010204081020
Если вы хотите более компактное представление, вы можете использовать Base64:
string base64 = Convert.ToBase64String(data);
Результат: AQIECBAg
Я подумал, что попытаюсь сравнить скорость каждого из перечисленных здесь методов, черт побери. Я основал код тестирования скорости на этом.
В результате BitConverter+String.Replace выглядит быстрее, чем большинство других простых способов. Но скорость можно улучшить с помощью таких алгоритмов, как ByteArrayToHexString Натана Моинвазири или ToHex Курта.
Мне также было интересно, что string.Concat и string.Join намного медленнее, чем реализации StringBuilder для длинных строк, но похожи для более коротких массивов. Вероятно, из-за расширения StringBuilder на более длинные строки, поэтому установка начального размера должна сводить на нет эту разницу.
- Взял каждый бит кода из ответа здесь:
- BitConvertRep = Ответ от Guffa, BitConverter и String.Replace (я рекомендую в большинстве случаев)
- StringBuilder = Ответ Квинтина Робинсона, foreach char StringBuilder.Append
- LinqConcat = Ответ от Michael Buen, string.Concat из встроенного массива Linq
- LinqJoin = Ответ от mloskot, string.Join встроенного массива Linq
- LinqAgg = Ответ Мэтью Уайтед, IEnumerable. Агрегат с StringBuilder
- ToHex = Answer by Kurt, устанавливает символы в массиве, используя байтовые значения для получения hex
- ByteArrayToHexString = Ответ Натана Моинвазири, примерно с той же скоростью, что и вышеупомянутый ToHex, и, вероятно, его легче читать (я бы порекомендовал для скорости)
- ToHexFromTable = Связано в ответе Натаном Моинвазири, для меня это примерно такая же скорость, как в приведенных выше 2, но для этого всегда требуется массив из 256 строк
С:
LONG_STRING_LENGTH = 1000 * 1024;
- BitConvertRep Расчет времени истек 27 202 мс (самый быстрый встроенный / простой)
- Время вычисления StringBuilder истекло 75 723 мс (StringBuilder не перераспределен)
- Расчет времени LinqConcat истек 182 094 мс
- LinqJoin Расчет времени истек 181,142 мс
- Время расчета LinqAgg 93,087 мс (StringBuilder с перераспределением)
- Время расчета ToHex 19,167 мс (самое быстрое)
С:
LONG_STRING_LENGTH = 100 * 1024;
, Похожие результаты
- BitConvertReplace вычисление истекшего времени 3431 мс
- Время вычисления StringBuilder 8289 мс
- LinqConcat расчет времени истек 21512 мс
- LinqJoin вычисление истекшее время 19433 мс
- Время расчета LinqAgg 9230 мс
- ToHex Расчет истекшего времени 1976 мс
С:
int MANY_STRING_COUNT = 1000;
int MANY_STRING_LENGTH = 1024;
(Тот же счетчик байтов, что и в первом тесте, но в разных массивах)
- BitConvertReplace вычисление истекшего времени 25,680 мс
- Время вычисления StringBuilder 78,411 мс
- Расчет времени LinqConcat истек 101 233 мс
- LinqJoin расчет времени истек 99,311 мс
- Время вычисления LinqAgg истекло 84,660 мс
- Время расчета истекло 18 221 мс
С:
int MANY_STRING_COUNT = 2000;
int MANY_STRING_LENGTH = 20;
- BitConvertReplace вычисление истекшего времени 1347 мс
- Время вычисления StringBuilder 3234 мс
- Расчет LinqConcat истекшего времени 5013 мс
- LinqJoin Расчет времени истек 4826 мс
- Время расчета LinqAgg 3589 мс
- ToHex Расчет истекшего времени 772 мс
Код тестирования, который я использовал:
void Main()
{
int LONG_STRING_LENGTH = 100 * 1024;
int MANY_STRING_COUNT = 1024;
int MANY_STRING_LENGTH = 100;
var source = GetRandomBytes(LONG_STRING_LENGTH);
List<byte[]> manyString = new List<byte[]>(MANY_STRING_COUNT);
for (int i = 0; i < MANY_STRING_COUNT; ++i)
{
manyString.Add(GetRandomBytes(MANY_STRING_LENGTH));
}
var algorithms = new Dictionary<string,Func<byte[], string>>();
algorithms["BitConvertReplace"] = BitConv;
algorithms["StringBuilder"] = StringBuilderTest;
algorithms["LinqConcat"] = LinqConcat;
algorithms["LinqJoin"] = LinqJoin;
algorithms["LinqAgg"] = LinqAgg;
algorithms["ToHex"] = ToHex;
algorithms["ByteArrayToHexString"] = ByteArrayToHexString;
Console.WriteLine(" === Long string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
pair.Value(source);
});
}
Console.WriteLine(" === Many string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
foreach (var str in manyString)
{
pair.Value(str);
}
});
}
}
// Define other methods and classes here
static void TimeAction(string description, int iterations, Action func) {
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
//static byte[] GetRandomBytes(int count) {
// var bytes = new byte[count];
// (new Random()).NextBytes(bytes);
// return bytes;
//}
static Random rand = new Random();
static byte[] GetRandomBytes(int count) {
var bytes = new byte[count];
rand.NextBytes(bytes);
return bytes;
}
static string BitConv(byte[] data)
{
return BitConverter.ToString(data).Replace("-", string.Empty);
}
static string StringBuilderTest(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length*2);
foreach (byte b in data)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
static string LinqConcat(byte[] data)
{
return string.Concat(data.Select(b => b.ToString("X2")).ToArray());
}
static string LinqJoin(byte[] data)
{
return string.Join("",
data.Select(
bin => bin.ToString("X2")
).ToArray());
}
static string LinqAgg(byte[] data)
{
return data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();
}
static string ToHex(byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');
b = ((byte)(bytes[bx] & 0x0F));
c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');
}
return new string(c);
}
public static string ByteArrayToHexString(byte[] Bytes)
{
StringBuilder Result = new StringBuilder(Bytes.Length*2);
string HexAlphabet = "0123456789ABCDEF";
foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}
return Result.ToString();
}
Также еще один ответ с похожим процессом, я еще не сравнивал наши результаты.
Гекс, Линк-фу:
string.Concat(ba.Select(b => b.ToString("X2")).ToArray())
ОБНОВЛЕНИЕ со временем
Как отмечает @RubenBartelink, код, который не имеет преобразования IEnumerable<string>
в массив: ba.Select(b => b.ToString("X2"))
не работает до 4.0, тот же код сейчас работает на 4.0.
Этот код...
byte[] ba = { 1, 2, 4, 8, 16, 32 };
string s = string.Concat(ba.Select(b => b.ToString("X2")));
string t = string.Concat(ba.Select(b => b.ToString("X2")).ToArray());
Console.WriteLine (s);
Console.WriteLine (t);
... до.NET 4.0 вывод выглядит так:
System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[System.Byte,System.String]
010204081020
Начиная с.NET 4.0, string.Concat имеет перегрузку, которая принимает IEnumerable. Следовательно, на 4.0 вышеприведенный код будет иметь одинаковые выходные данные для переменных s и t
010204081020
010204081020
До 4.0, ba.Select(b => b.ToString("X2"))
идет перегрузить (object arg0)
путь для IEnumerable<string>
перейти к правильной перегрузке, т.е. (params string[] values)
, нам нужно преобразовать IEnumerable<string>
в массив строк. До 4.0 у string.Concat было 10 функций перегрузки, на 4.0 теперь 12
Вот еще один метод:
public static string ByteArrayToHexString(byte[] Bytes)
{
StringBuilder Result = new StringBuilder(Bytes.Length * 2);
string HexAlphabet = "0123456789ABCDEF";
foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}
return Result.ToString();
}
public static byte[] HexStringToByteArray(string Hex)
{
byte[] Bytes = new byte[Hex.Length / 2];
int[] HexValue = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
for (int x = 0, i = 0; i < Hex.Length; i += 2, x += 1)
{
Bytes[x] = (byte)(HexValue[Char.ToUpper(Hex[i + 0]) - '0'] << 4 |
HexValue[Char.ToUpper(Hex[i + 1]) - '0']);
}
return Bytes;
}
В качестве альтернативы, вы можете предварительно создать таблицу перевода, чтобы добиться еще более быстрых результатов:
Мне нравится использовать методы расширения для таких преобразований, даже если они просто обертывают стандартные методы библиотеки. В случае шестнадцатеричных преобразований я использую следующие вручную настроенные (т.е. быстрые) алгоритмы:
public static string ToHex(this byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
b = ((byte)(bytes[bx] & 0x0F));
c[++cx]=(char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
}
return new string(c);
}
public static byte[] HexToBytes(this string str)
{
if (str.Length == 0 || str.Length % 2 != 0)
return new byte[0];
byte[] buffer = new byte[str.Length / 2];
char c;
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
{
// Convert first half of byte
c = str[sx];
buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);
// Convert second half of byte
c = str[++sx];
buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
}
return buffer;
}
Ну, я не часто конвертирую байты в шестнадцатеричные, поэтому должен сказать, что не знаю, есть ли лучший способ, чем это, но вот способ сделать это.
StringBuilder sb = new StringBuilder();
foreach (byte b in myByteArray)
sb.Append(b.ToString("X2"));
string hexString = sb.ToString();
Очень быстрые методы расширения (с обращением):
public static class ExtensionMethods {
public static string ToHex(this byte[] data) {
return ToHex(data, "");
}
public static string ToHex(this byte[] data, string prefix) {
char[] lookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
int i = 0, p = prefix.Length, l = data.Length;
char[] c = new char[l * 2 + p];
byte d;
for(; i < p; ++i) c[i] = prefix[i];
i = -1;
--l;
--p;
while(i < l) {
d = data[++i];
c[++p] = lookup[d >> 4];
c[++p] = lookup[d & 0xF];
}
return new string(c, 0, c.Length);
}
public static byte[] FromHex(this string str) {
return FromHex(str, 0, 0, 0);
}
public static byte[] FromHex(this string str, int offset, int step) {
return FromHex(str, offset, step, 0);
}
public static byte[] FromHex(this string str, int offset, int step, int tail) {
byte[] b = new byte[(str.Length - offset - tail + step) / (2 + step)];
byte c1, c2;
int l = str.Length - tail;
int s = step + 1;
for(int y = 0, x = offset; x < l; ++y, x += s) {
c1 = (byte)str[x];
if(c1 > 0x60) c1 -= 0x57;
else if(c1 > 0x40) c1 -= 0x37;
else c1 -= 0x30;
c2 = (byte)str[++x];
if(c2 > 0x60) c2 -= 0x57;
else if(c2 > 0x40) c2 -= 0x37;
else c2 -= 0x30;
b[y] = (byte)((c1 << 4) + c2);
}
return b;
}
}
Побеждает всех остальных в тесте скорости выше:
=== Тест длинной строки
BitConvertReplace вычисление истекшего времени 2415 мс
Время вычисления StringBuilder 5668 мс
Расчет LinqConcat прошедшего времени 11826 мс
LinqJoin Расчет времени истек 9323 мс
Время расчета LinqAgg 7444 мс
ToHexTable Расчет времени истек 1028 мс
ToHexAcidzombie Расчет истекшего времени 1035 мс
ToHexPatrick Расчет времени истек 814 мс
ToHexKurt Расчет истекшего времени 1604 мс
ByteArrayToHexString Расчет истекшего времени 1330 мс=== Струнный тест
BitConvertReplace вычисление истекшего времени 2238 мс
Время вычисления StringBuilder 5393 мс
Расчет LinqConcat истекшее время 9043 мс
LinqJoin вычисление истекшее время 9131 мс
Время расчета LinqAgg 7324 мс
ToHexTable Расчет времени истек 968 мс
ToHexAcidzombie Расчет истекшего времени 969 мс
ToHexPatrick Расчет истекшего времени 956 мс
ToHexKurt Расчет истекшего времени 1547 мс
ByteArrayToHexString Расчет истекшего времени 1277 мс
Я думал, что должен дать ответ. Из моего теста этот метод самый быстрый
public static class Helper
{
public static string[] HexTbl = Enumerable.Range(0, 256).Select(v => v.ToString("X2")).ToArray();
public static string ToHex(this IEnumerable<byte> array)
{
StringBuilder s = new StringBuilder();
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
public static string ToHex(this byte[] array)
{
StringBuilder s = new StringBuilder(array.Length*2);
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
}
Просто, чтобы добавить еще один ответ в кучу, есть System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary
класс, который я использовал, который может конвертировать байты в и из шестнадцатеричного:
string hex = new SoapHexBinary(bytes).ToString();
byte[] bytes = SoapHexBinary.Parse(hex).Value;
Не уверен, как он сравнивает (тест) с другими реализациями, но IMO это довольно просто - особенно для преобразования из шестнадцатеричного обратно в байты.
С:
byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x0D, 0x0E, 0x0F };
string hex = string.Empty;
data.ToList().ForEach(b => hex += b.ToString("x2"));
// use "X2" for uppercase hex letters
Console.WriteLine(hex);
Результат: 0102030d0e0f
Вы должны знать кодировку строки, представленной в байтах, но вы можете сказать, System.Text.UTF8Encoding.GetString(bytes)
или же System.Text.ASCIIEncoding.GetString(bytes)
, (Я делаю это по памяти, поэтому API может быть не совсем правильным, но это очень близко.)
Для ответа на ваш второй вопрос, посмотрите этот вопрос.
Вот метод расширения для байтового массива (byte[]), например,
var b = new byte[] { 15, 22, 255, 84, 45, 65, 7, 28, 59, 10 };
Console.WriteLine(b.ToHexString());
public static class HexByteArrayExtensionMethods
{
private const int AllocateThreshold = 256;
private const string UpperHexChars = "0123456789ABCDEF";
private const string LowerhexChars = "0123456789abcdef";
private static string[] upperHexBytes;
private static string[] lowerHexBytes;
public static string ToHexString(this byte[] value)
{
return ToHexString(value, false);
}
public static string ToHexString(this byte[] value, bool upperCase)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value.Length == 0)
{
return string.Empty;
}
if (upperCase)
{
if (upperHexBytes != null)
{
return ToHexStringFast(value, upperHexBytes);
}
if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, UpperHexBytes);
}
return ToHexStringSlow(value, UpperHexChars);
}
if (lowerHexBytes != null)
{
return ToHexStringFast(value, lowerHexBytes);
}
if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, LowerHexBytes);
}
return ToHexStringSlow(value, LowerhexChars);
}
private static string ToHexStringSlow(byte[] value, string hexChars)
{
var hex = new char[value.Length * 2];
int j = 0;
for (var i = 0; i < value.Length; i++)
{
var b = value[i];
hex[j++] = hexChars[b >> 4];
hex[j++] = hexChars[b & 15];
}
return new string(hex);
}
private static string ToHexStringFast(byte[] value, string[] hexBytes)
{
var hex = new char[value.Length * 2];
int j = 0;
for (var i = 0; i < value.Length; i++)
{
var s = hexBytes[value[i]];
hex[j++] = s[0];
hex[j++] = s[1];
}
return new string(hex);
}
private static string[] UpperHexBytes
{
get
{
return (upperHexBytes ?? (upperHexBytes = new[] {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" }));
}
}
private static string[] LowerHexBytes
{
get
{
return (lowerHexBytes ?? (lowerHexBytes = new[] {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" }));
}
}
}
Никто здесь не упомянул причину, почему вы получаете строку "System.Byte[]" вместо значения, так что я буду.
Когда объект неявно приведен к String, программа по умолчанию будет использовать объект public String ToString()
метод, который унаследован от System.Object
:
public virtual string ToString()
{
return this.GetType().ToString();
}
Если вы обнаружите, что вы часто делаете это преобразование, вы можете просто создать класс-оболочку и переопределить этот метод следующим образом:
public override string ToString()
{
// do the processing here
// return the nicely formatted string
}
Теперь каждый раз, когда вы печатаете этот объект-обертку, вы получите значение вместо значения из this.GetType().ToString()
,
Вы объединяете LINQ со строковыми методами:
string hex = string.Join("",
bin.Select(
bin => bin.ToString("X2")
).ToArray());
Как уже говорили другие, это зависит от кодировки значений в байтовом массиве. Несмотря на это, вы должны быть очень осторожны с такими вещами, или вы можете попытаться преобразовать байты, которые не обрабатываются выбранной кодировкой.
У Джона Скита есть хорошая статья о кодировании и юникоде в.NET. Рекомендуемое чтение.
Я не уверен, если вам нужна производительность для этого, но вот самый быстрый способ конвертировать byte[] в шестнадцатеричную строку, о которой я могу думать:
static readonly char[] hexchar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string HexStr(byte[] data, int offset, int len, bool space = false)
{
int i = 0, k = 2;
if (space) k++;
var c = new char[len * k];
while (i < len)
{
byte d = data[offset + i];
c[i * k] = hexchar[d / 0x10];
c[i * k + 1] = hexchar[d % 0x10];
if (space && i < len - 1) c[i * k + 2] = ' ';
i++;
}
return new string(c, 0, c.Length);
}
Я думаю, что я сделал более быстрый байтовый массив для преобразования строк:
public static class HexTable
{
private static readonly string[] table = BitConverter.ToString(Enumerable.Range(0, 256).Select(x => (byte)x).ToArray()).Split('-');
public static string ToHexTable(byte[] value)
{
StringBuilder sb = new StringBuilder(2 * value.Length);
for (int i = 0; i < value.Length; i++)
sb.Append(table[value[i]]);
return sb.ToString();
}
И тест настроен:
static void Main(string[] args)
{
const int TEST_COUNT = 10000;
const int BUFFER_LENGTH = 100000;
Random random = new Random();
Stopwatch sw = new Stopwatch();
Stopwatch sw2 = new Stopwatch();
byte[] buffer = new byte[BUFFER_LENGTH];
random.NextBytes(buffer);
sw.Start();
for (int j = 0; j < TEST_COUNT; j++)
HexTable.ToHexTable(buffer);
sw.Stop();
sw2.Start();
for (int j = 0; j < TEST_COUNT; j++)
ToHexChar.ToHex(buffer);
sw2.Stop();
Console.WriteLine("Hex Table Elapsed Milliseconds: {0}", sw.ElapsedMilliseconds);
Console.WriteLine("ToHex Elapsed Milliseconds: {0}", sw2.ElapsedMilliseconds);
}
Метод ToHexChar.ToHEx() - это метод ToHex(), показанный ранее.
Результаты следующие:
HexTable = 11808 мсToHEx = 12168 мс
Это может показаться не так уж много различий, но это все еще быстрее:)
Хороший способ сделать это с помощью LINQ...
var data = new byte[] { 1, 2, 4, 8, 16, 32 };
var hexString = data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();
private static string GuidToRaw(Guid guid)
{
byte[] bytes = guid.ToByteArray();
int сharCount = bytes.Length * 2;
char[] chars = new char[сharCount];
int index = 0;
for (int i = 0; i < сharCount; i += 2)
{
byte b = bytes[index++];
chars[i] = GetHexValue((int)(b / 16));
chars[i + 1] = GetHexValue((int)(b % 16));
}
return new string(chars, 0, chars.Length);
}
private static char GetHexValue(int i)
{
return (char)(i < 10 ? i + 48 : i + 55);
}