2008-11-26 18 views
196

Czy możemy przekonwertować ciąg szesnastkowy na tablicę bajtów za pomocą wbudowanej funkcji w języku C#, czy muszę wykonać niestandardową metodę dla tego?Jak przekonwertować łańcuch szesnastkowy na tablicę bajtów?

+1

można łatwo przekonwertować ciąg byte [] w jednym wierszu: var tablicaBitowa = Encoding.ASCII.GetBytes (string_with_your_data); –

+9

@ mik-T, łańcuch szesnastkowy ma format w rodzaju 219098C10D7, który co dwa znaki konwertuje na jeden bajt. Twoja metoda nie nadaje się do użytku. – AaA

+2

To pytanie nie wydaje się być duplikatem wybranego pytania. ten konwertuje FROM szesnastkowy na tablicę bajtową, jednak inne pytanie konwertuje tablicę bajtową na szesnastkową. – AaA

Odpowiedz

386

Oto fajny zabawny przykład LINQ.

public static byte[] StringToByteArray(string hex) { 
    return Enumerable.Range(0, hex.Length) 
        .Where(x => x % 2 == 0) 
        .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) 
        .ToArray(); 
} 
+84

** Dobre niebiosa !! ** Czy zdajesz sobie sprawę, jak NIEBEZPIECZNY to jest ??? Oczywiście, jest fajnie, ale LINQ jest nadużywany za rzeczy, które powinny być wykonane inaczej! Kod LINQ wymaga .NET 3.5 i wymaga odniesienia do System.Core (który w innym przypadku nie byłby potrzebny). Zobacz duplikat artykułu, aby uzyskać skuteczne rozwiązania. –

+17

To prawdopodobnie miało być zabawne, nieskuteczne. – Karsten

+1

Ta odpowiedź ma co najmniej dodatkową zaletę, że można ją skompilować. keyAsBytes jest niezdefiniowany w drugim. –

35
public static byte[] ConvertHexStringToByteArray(string hexString) 
{ 
    if (hexString.Length % 2 != 0) 
    { 
     throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString)); 
    } 

    byte[] HexAsBytes = new byte[hexString.Length/2]; 
    for (int index = 0; index < HexAsBytes.Length; index++) 
    { 
     string byteValue = hexString.Substring(index * 2, 2); 
     HexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture); 
    } 

    return HexAsBytes; 
} 
+0

Czy nie powinno to być "dla (int index = 0; index Noli

54

Zrobiłem rozeznanie i okazało się, że byte.Parse jest jeszcze wolniej niż Convert.ToByte. Najszybsza konwersja, jaką mogłem wymyślić, to około 15 znaczników na bajt.

public static byte[] StringToByteArrayFastest(string hex) { 
     if (hex.Length % 2 == 1) 
      throw new Exception("The binary key cannot have an odd number of digits"); 

     byte[] arr = new byte[hex.Length >> 1]; 

     for (int i = 0; i <hex.Length>> 1; ++i) 
     { 
      arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); 
     } 

     return arr; 
    } 

    public static int GetHexVal(char hex) { 
     int val = (int)hex; 
     //For uppercase A-F letters: 
     return val - (val < 58 ? 48 : 55); 
     //For lowercase a-f letters: 
     //return val - (val < 58 ? 48 : 87); 
     //Or the two combined, but a bit slower: 
     //return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); 
    } 

// działa również na .NET Micro Framework, gdzie (w SDK4.3) byte.Parse (string) dopuszcza tylko formatów całkowitych.

+0

Byłoby lepiej, gdyby funkcja GetHexVal była wbudowana. –

+2

Próbowałem, ale jakoś to jest nieco szybciej. Może dlatego, że różnica między stertą a stosem. – CainKellye

+0

Hmmm dziwne. Testowałem go z VB.NET 2.0 (2010 kompilator) x86 używając jego potrójnego operatora if() i zdecydowanie szybciej. I generalnie, czy operatorzy IL nie powinni być szybsi niż jakiekolwiek wywołania funkcji? –

4

Myślę, że to może działać.

public static byte[] StrToByteArray(string str) 
    { 
     Dictionary<string, byte> hexindex = new Dictionary<string, byte>(); 
     for (int i = 0; i <= 255; i++) 
      hexindex.Add(i.ToString("X2"), (byte)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(); 
    } 
Powiązane problemy