Byte [] в шестнадцатеричную строку

Как преобразовать byte[] в string? Каждый раз, когда я пытаюсь, я получаю

System.Byte []

вместо значения.

Также, как мне получить значение в шестнадцатеричном виде вместо десятичного?

Ответы

Ответ 1

Для этого существует встроенный метод:

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

Ответ 2

Я думал, что попытаюсь сравнить скорость каждого из перечисленных здесь методов, черт возьми. Я основываю код проверки скорости на этом.

В результате BitConverter + String.Replace работает быстрее, чем большинство других простых способов. Но скорость может быть улучшена с помощью таких алгоритмов, как ByteArrayToHexString Натана Моинвазири или ToHex Курта.

Мне также было интересно, что string.Concat и string.Join намного медленнее реализаций StringBuilder для длинных строк, но аналогичны для более коротких массивов. Вероятно, из-за расширения StringBuilder на более длинных строках, поэтому установка начального размера должна отрицать эту разницу.

  • Взял каждый бит кода из ответа здесь:
  • BitConvertRep= Отвечать Guffa, BitConverter и String.Replace (я бы рекомендовал в большинстве случаев)
  • StringBuilder= Отвечать Quintin Robinson, foreach char StringBuilder.Append
  • LinqConcat= Отвечать Майклом Буэном, string.Concat из построенного массива Linq
  • LinqJoin= Отвечать на mloskot, string.Join из построенного массива Linq
  • LinqAgg= Отвечать Matthew Whited, IEnumerable.Aggregate with StringBuilder
  • ToHex= Ответ от Kurt, задает символы в массиве, используя байтовые значения для получения hex
  • ByteArrayToHexString= Ответ Натана Моинвазири, примерно такой же, как и ToHex, и, вероятно, легче читать (Я бы рекомендовал для скорости)
  • ToHexFromTable= Связанный с ответом Nathan Moinvaziri, для меня это примерно такая же скорость, что и выше 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 Время Истек 1933 мс
  • Расчет LinqAgg Истекшее время 9230 мс
  • Расчет ToHex Время, прошедшее 1976 мс

С помощью: int MANY_STRING_COUNT = 1000; int MANY_STRING_LENGTH = 1024;(Тот же байт считается первым, но в разных массивах)

  • Расчет BitConvertReplace Время Истек 25,680 мс
  • Расчет времени StringBuilder Время Истек 19,411 мс
  • Расчет LinqConcat Время Истек 101,233 мс
  • Расчет LinqJoin Истекшее время 99,311 мс
  • Расчет LinqAgg Истекшее время 84,660 мс
  • Расчет ToHex Истекшее время 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);
   Список < байт [] > manyString = new List < byte [] > (MANY_STRING_COUNT);   for (int я = 0; я < MANY_STRING_COUNT; ++ i)   {       manyString.Add(GetRandomBytes (MANY_STRING_LENGTH));   }
   var algorithmms = new Dictionary < string, Func < byte [], string > >();   алгоритмы [ "BitConvertReplace" ] = BitConv;   алгоритмы [ "StringBuilder" ] = StringBuilderTest;   алгоритмы [ "LinqConcat" ] = LinqConcat;   алгоритмы [ "LinqJoin" ] = LinqJoin;   алгоритмы [ "LinqAgg" ] = LinqAgg;   алгоритмы [ "ToHex" ] = ToHex;   алгоритмы [ "ByteArrayToHexString" ] = ByteArrayToHexString;
   Console.WriteLine( "=== Long string test" );   foreach (пара var в алгоритмах) {       TimeAction (pair.Key +  "расчет", 500,() = >       {           pair.Value(источник);       });   }
   Console.WriteLine( "=== Многие строковые тесты" );   foreach (пара var в алгоритмах) {       TimeAction (pair.Key +  "расчет", 500,() = >       {           foreach (var str in manyString)           {               pair.Value(ул);           }       });   }
}

// Определим другие методы и классы здесь
static void TimeAction (описание строки, int iterations, Action func) {   var watch = новый секундомер();   watch.Start();   for (int я = 0; я & iterations; я ++) {       FUNC();   }   watch.Stop();   Console.Write(описание);   Console.WriteLine( "Истекшее время {0} мс", watch.ElapsedMilliseconds);
}

// статический байт [] GetRandomBytes (int count) {
//var  bytes = new byte [count];
// (new Random()). NextBytes (bytes);
// вернуть байты;
// }
static Random rand = new Random();
static byte [] GetRandomBytes (int count) {   var bytes = новый байт [count];   rand.NextBytes(байты);   возвращать байты;
}


статическая строка BitConv (байт [])
{   return BitConverter.ToString(данные).Replace( "-", string.Empty);
}
статическая строка StringBuilderTest (байт [] data)
{   StringBuilder sb = new StringBuilder (data.Length * 2);   foreach (байт b в данных)       sb.append(b.ToString(  "Х2" ));
   return sb.ToString();
}
статическая строка LinqConcat (байт [])
{   return string.Concat(data.Select(b = > b.ToString( "X2" )). ToArray());
}
статическая строка LinqJoin (байт [])
{   return string.Join("",       data.Select(           bin = > bin.ToString( "X2" )           ).ToArray());
}
статическая строка LinqAgg (байт [])
{   return data.Aggregate(новый StringBuilder(),                              (SB, v) = > sb.append(v.ToString(  "Х2" ))                             ).Нанизывать();
}
статическая строка ToHex (byte [] bytes)
{   char [] c = новый char [bytes.Length * 2];
   байт b;
   for (int bx = 0, cx = 0; bx < bytes.Length; ++ bx, ++ cx)   {       b = ((байт) (байты [bx] > 4));       c [cx] = (char) (b > 9 & le; b - 10 + 'A': b + '0');
       b = ((байт) (байты [bx] & 0x0F));       c [++ cx] = (char) (b > 9? b - 10 + 'A': b + '0');   }
   вернуть новую строку (c);
}
public static string ByteArrayToHexString (byte [] Bytes)
{   StringBuilder Result = new StringBuilder (Bytes.Length * 2);   string HexAlphabet = "0123456789ABCDEF";
   foreach (байт B в байтах)       {       Result.Append(HexAlphabet [(int) (B > 4)]);       Result.Append(HexAlphabet [(int) (B & 0xF)]);       }
   return Result.ToString();
}
Код>

Еще один ответ с аналогичным процессом, я еще не сравнил наши результаты.

Ответ 3

Hex, Linq-fu:

string.Concat(ba.Select(b => b.ToString("X2")).ToArray())

UPDATE со временем

Как отмечено @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

Ответ 4

Мне нравится использовать методы расширения для таких преобразований, даже если они просто обертывают стандартные библиотечные методы. В случае шестнадцатеричных преобразований я использую следующие ручные (то есть быстрые) алгоритмы:

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;
}

Ответ 5

Вот еще один способ:

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;
}

В качестве альтернативы вы можете предварительно построить таблицу переводов, чтобы добиться еще более быстрых результатов:

http://blogs.msdn.com/b/blambert/archive/2009/02/22/blambert-codesnip-fast-byte-array-to-hex-string-conversion.aspx

Ответ 6

Ну, я не часто конвертирую байты в шестнадцатеричный, поэтому я должен сказать, что не знаю, есть ли лучший способ, но это способ сделать это.

StringBuilder sb = new StringBuilder();
foreach (byte b in myByteArray)
    sb.Append(b.ToString("X2"));

string hexString = sb.ToString();

Ответ 7

Я думал, что должен дать ответ. Из моего теста этот метод является самым быстрым

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();
    }
}

Ответ 8

Очень быстрые методы расширения (с разворотом):

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 Время Истек 2568 ms
Расчет LinqConcat Истекшее время 11826 ms
Расчет LinqJoin Истекшее время 9323 мс
Расчет LinqAgg Истекшее время 7444 мс
Расчет ToHexTable Время Истек 1028 мс
Расчет ToHexAcidzombie Время Истек 1035 мс
Расчет ToHexPatrick Истекшее время 814 мс
ToHexKurt расчетное время Истек 1604 мс
Расчет ByteArrayToHexString Время Истек 1330 мс

=== Многие строковые тесты
Расчет BitConvertReplace Время Истек 2238 мс
Расчет StringBuilder Время истекло 5393 ms
Расчет LinqConcat Истекшее время 9043 мс
Расчет LinqJoin Истекшее время 9131 мс
Расчет LinqAgg Истекшее время 7324 мс
Расчет ToHexTable Истекшее время 968 ms
Расчет ToHexAcidzombie Истекшее время 969 ms
Расчет ToHexPatrick Истекшее время 956 мс
Расчет ToHexKurt Истекшее время 1547 мс
Расчет ByteArrayToHexString Время Истекшее 1277 мс

Ответ 9

Чтобы добавить еще один ответ в кучу, существует класс System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary, который я использовал, который может конвертировать байты в и из шестнадцатеричного:

string hex = new SoapHexBinary(bytes).ToString();
byte[] bytes = SoapHexBinary.Parse(hex).Value;

Не уверен, как он сравнивает (сравнительный тест) с другими реализациями, но IMO это довольно просто - особенно для преобразования из шестнадцатеричного обратно в байты.

Ответ 10

С

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

Ответ 11

Вы комбинируете LINQ со строковыми методами:

string hex = string.Join("",
  bin.Select(
    bin => bin.ToString("X2")
      ).ToArray());

Ответ 12

Вам нужно знать кодировку строки, представленной в байтах, но вы можете сказать System.Text.UTF8Encoding.GetString(bytes) или System.Text.ASCIIEncoding.GetString(bytes). (Я делаю это из памяти, поэтому API может быть не совсем корректным, но он очень близок.)

Для ответа на второй вопрос см. этот вопрос.

Ответ 13

Как говорили другие, это зависит от кодирования значений в массиве байтов. Несмотря на это, вы должны быть очень осторожны с подобными вещами или можете попытаться преобразовать байты, которые не обрабатываются выбранной кодировкой.

У Jon Skeet есть хорошая статья о кодировании и юникоде в .NET. Рекомендуемое чтение.

Ответ 14

Я думаю, что я сделал более быстрый байт-массив для строкового преобразователя:

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мс

Возможно, это не очень большая разница, но она еще быстрее:)

Ответ 15

Никто здесь не упоминает причину, по которой вы получаете строку "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().

Ответ 16

Я не уверен, нужна ли вам производительность для этого, но вот самый быстрый способ преобразования байта [] в шестнадцатеричную строку, о которой я могу думать:

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);
}

Ответ 17

Хороший способ сделать это с помощью 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();

Ответ 18

Вот метод расширения для байтового массива (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" }));
        }
    }
}

Ответ 19

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);
}