programing

바이트[] ~ 16진수 문자열

easyjava 2023. 4. 14. 22:17
반응형

바이트[] ~ 16진수 문자열

「」를 해야 ?byte[] a까지string시도 할 때마다, 나는 그것을 얻습니다.

System.Byte[]

값을 대신해서.

또한 소수점 대신 16진수로 값을 얻는 방법은 무엇입니까?

여기에는 다음과 같은 기본 제공 방법이 있습니다.

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

.Net5.0 업데이트

@antoninkriz의 벤치마크 비교 덕분에 오늘날 확실한 승자를 알 수 있습니다.

다른 걸 쓰면 바보가 돼Convert.ToHexString가독성, 퍼포먼스, 안전성 면에서 확실히 유리하다고 생각합니다.


나머지는 2012년 4월 10일 이전입니다.

여기에 나와 있는 각 방법의 속도를 비교해 보려고 합니다.속도 테스트 코드는 이걸 근거로 삼았어요

그 결과 BitConverter+String이 생성됩니다.다른 대부분의 간단한 방법보다 교환이 더 빠른 것 같습니다.그러나 Nathan Moinvaziri의 ByteArrayToxHexString이나 Kurt의 ToHex와 같은 알고리즘으로 속도를 향상시킬 수 있습니다.

저도 그 끈이 재미있었어요.콘캣과 스트링긴 문자열의 경우 String Builder 구현보다 가입 속도가 훨씬 느리지만 짧은 배열의 경우 비슷합니다.긴 문자열로 String Builder를 확장한 것이 원인일 수 있으므로 초기 크기를 설정하면 이 차이가 무효가 됩니다.

  • 여기 답변에서 각 코드의 비트를 가져왔습니다.
  • BitConvertRep = Guffa, BitConverter 및 String에 의한 응답입니다.대체(대부분의 경우 [edit:]를 사용할 수 없는 경우 권장)
  • StringBuilder = Quintin Robinson이 응답하고 Char StringBuilder를 검색합니다.추가
  • LinqConcat = Michael Buen의 답변, 문자열.Linq 빌드 어레이의 Concat
  • LinqJoin = mloskot, 문자열로 응답합니다.Linq 빌드 어레이의 결합
  • LinqAgg = Matthew Whited, IENumerable의 답변.String Builder를 사용한 집약
  • ToHex = Kurt 응답, 배열에 문자를 설정하고 바이트 값을 사용하여 16진수를 가져옵니다.
  • ByteArrayToHexString = Nathan Moinvaziri의 답변은 위의 ToHex와 거의 같은 속도이며 읽기 쉬울 입니다(속도를 위해서는 [edit:]를 사용할 수 없는 경우).
  • ToHexFromTable = Nathan Moinvaziri가 응답한 링크. 위의 2와 거의 같은 속도이지만 항상 256개의 문자열 배열이 필요합니다.

★★★★★★★LONG_STRING_LENGTH = 1000 * 1024;

  • BitConvertRep 계산 시간 경과 27,202 ms(가장 빠른 내장/심플)
  • String Builder 계산 경과 시간 75,723 ms(String Builder 재할당 없음)
  • LinqConcat 계산 시간 경과 시간 182,094 ms
  • LinqJoin 계산 시간 경과 시간 181,142 ms
  • LinqAgg 계산 시간 경과 시간 93,087 ms(재할당이 있는 StringBuilder)
  • ToHex 계산 경과 시간 19,167 ms(최고속)

★★★★★★★LONG_STRING_LENGTH = 100 * 1024; 결과, 「 」

  • BitConvertReplace 계산 경과 시간 3431ms
  • StringBuilder 계산 경과 시간 8289ms
  • LinqConcat 계산 경과 시간 21512ms
  • LinqJoin 계산 시간 경과 19433ms
  • LinqAgg 계산 경과 시간 9230 ms
  • ToHex 계산 시간 경과 1976 ms

★★★★★★★int MANY_STRING_COUNT = 1000; int MANY_STRING_LENGTH = 1024; 번째 와 같은 배열은 ).

  • BitConvertReplace 계산시간 경과 25,680밀리초
  • StringBuilder 계산 경과 시간 78,411 ms
  • LinqConcat 계산 경과 시간 101,233 ms
  • LinqJoin 계산 시간 경과 99,311ms
  • LinqAgg 계산 경과 시간 84,660 ms
  • ToHex 계산 경과 시간 18,221 ms

★★★★★★★int MANY_STRING_COUNT = 2000; int MANY_STRING_LENGTH = 20;

  • BitConvertReplace 계산 경과시간 1347밀리초
  • StringBuilder 계산 경과 시간 3234ms
  • LinqConcat 계산 경과 시간 5013ms
  • LinqJoin 계산 시간 경과 4826ms
  • LinqAgg 계산 경과 시간 3589 ms
  • ToHex 계산 시간 경과 시간 772 ms

사용한 테스트 코드:

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

비슷한 과정을 거친다른 답변입니다만, 저는 아직 결과를 비교하지 않았습니다.

16진수, Linq-fu:

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

시대에 맞게 업데이트

@ 수 @RubenBartelink 입니다.IEnumerable<string>에 : 레레 :ba.Select(b => b.ToString("X2"))4.0보다 버전에서는 4.0 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 4.0은ba.Select(b => b.ToString("X2"))(object arg0)의, 「」의IEnumerable<string>과부하가 (params string[] values) 「」를 ?IEnumerable<string>스트링 배열로 이동합니다.4에서는 string4.0으로 설정되어 있었습니다.함수가 4. 12Concat 10이 .

다음은 다른 방법입니다.

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

표준 라이브러리 메서드를 랩하는 경우에도 이러한 변환에 확장 메서드를 사용하는 것이 좋습니다.16진수 변환의 경우 다음과 같은 수동 조정(즉, 고속) 알고리즘을 사용합니다.

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

바이트를 16진수로 변환하는 일은 별로 없기 때문에 이것보다 더 좋은 방법이 있을지 모르겠지만, 여기 방법이 있습니다.

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

string hexString = sb.ToString();

대답을 해야겠다고 생각했어요.내 테스트로는 이 방법이 가장 빠르다.

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

고속 확장 방식(반전):

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 2415ms
Builder 5668msString Builder 5668ms
11826msLinqConcat 11826ms
9323msLinqJoin 9323ms
7444ms
msToHexTable 1028 ms
1035msToHexAcidzombie 1035ms
ToHexPatrick 계산 경과 시간 814 ms
msToHexKurt 1604 ms
1330밀리초

=== 문자열 테스트다중 문자열 테스트
2238msBitConvertReplace " 2238ms"
Builder Builder 5393ms
9043msLinqConcat 9043ms
9131msLinqJoin 9131ms
msLinqAgg 7324 ms
msToHexTable 968 ms
969msToHexAcidzombie 969ms
ToHexPatrick 계산 경과 시간 956 ms
1547msToHexKurt 1547ms
1277msByteArrayToHexString 1277ms

더 , '일단이라는 답이 .System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary16진수로 하거나 16진수로 할 수입니다.

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

(벤치마크)가 다른 구현과 어떻게 비교되는지는 확실하지 않지만 IMO는 매우 간단합니다. 특히 16진수에서 바이트로 변환하는 경우에는 더욱 그렇습니다.

포함:

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

LINQ를 문자열 메서드와 결합합니다.

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

"시스템"을 사용하는 이유에 대해서는 아무도 언급하지 않았습니다.값이 아닌 바이트[]" 문자열이므로 그렇게 하겠습니다.

오브젝트가 암묵적으로 문자열에 캐스팅되면 프로그램은 기본적으로 오브젝트의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().

다른 사용자가 말했듯이 이는 바이트 배열의 값 인코딩에 따라 달라집니다.이 경우에도 이런 종류의 작업에 매우 주의해야 합니다.그렇지 않으면 선택한 인코딩으로 처리되지 않는 바이트를 변환하려고 할 수 있습니다.

Jon Sket은 부호화와 유니코드에 관한 좋은 기사를 에 게재하고 있습니다.NET. 권장 읽을거리입니다.

문자열 변환기로의 고속 바이트 배열을 만든 것 같습니다.

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 ms ToHEX = 12168 ms

큰 차이는 없어 보이지만 그래도 더 빠릅니다.

퍼포먼스가 필요한지는 모르겠지만 바이트[]를 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);
}

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

언급URL : https://stackoverflow.com/questions/623104/byte-to-hex-string

반응형