Comment convertir hex en tableau d’octets?

J’ai copié et collé ces données binarys sur le serveur SQL, que je ne peux pas interroger pour le moment.

0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB25507EBFCD5223B 

Comment le reconvertir en tableau d’octets en c #?

Quelque chose comme ça:

 using System; public static class Parser { static void Main() { ssortingng hex = "0xBAC893CAB8B7FE03C927417A2A3F6A6" + "0BD30FF35E250011CB25507EBFCD5223B"; byte[] parsed = ParseHex(hex); // Just for confirmation... Console.WriteLine(BitConverter.ToSsortingng(parsed)); } public static byte[] ParseHex(ssortingng hex) { int offset = hex.StartsWith("0x") ? 2 : 0; if ((hex.Length % 2) != 0) { throw new ArgumentException("Invalid length: " + hex.Length); } byte[] ret = new byte[(hex.Length-offset)/2]; for (int i=0; i < ret.Length; i++) { ret[i] = (byte) ((ParseNybble(hex[offset]) << 4) | ParseNybble(hex[offset+1])); offset += 2; } return ret; } static int ParseNybble(char c) { if (c >= '0' && c <= '9') { return c-'0'; } if (c >= 'A' && c <= 'F') { return c-'A'+10; } if (c >= 'a' && c <= 'f') { return c-'a'+10; } throw new ArgumentException("Invalid hex digit: " + c); } } 

(EDIT: légèrement plus efficace - aucune sous-chaîne requirejse ...)

Il est possible que ParseNybble soit plus efficace. Par exemple, un commutateur / boîtier peut être plus efficace:

  static int ParseNybble(char c) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return c-'0'; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return c-'A'+10; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': return c-'a'+10; } throw new ArgumentException("Invalid hex digit: " + c); } 

ou éventuellement un tableau de recherche:

  // Omitted for brevity... I'm sure you get the gist private static readonly int[] NybbleLookup = BuildLookup(); private int ParseNybble(char c) { if (c > 'f') { throw new ArgumentException("Invalid hex digit: " + c); } int ret = NybbleLookup[c]; if (ret == -1) { throw new ArgumentException("Invalid hex digit: " + c); } return ret; } 

Je n'ai évalué aucun de ces éléments et je ne sais pas lequel serait le plus rapide. La solution actuelle est probablement la plus simple.

Envisagez de tirer parti d’une classe Framework qui expose déjà la possibilité d’effectuer une conversion hexadécimale, XmlReader par exemple:

 public static byte[] HexToBytes(this ssortingng hexEncodedBytes, int start, int end) { int length = end - start; const ssortingng tagName = "hex"; ssortingng fakeXmlDocument = Ssortingng.Format("<{1}>{0}", hexEncodedBytes.Subssortingng(start, length), tagName); var stream = new MemoryStream(Encoding.ASCII.GetBytes(fakeXmlDocument)); XmlReader reader = XmlReader.Create(stream, new XmlReaderSettings()); int hexLength = length / 2; byte[] result = new byte[hexLength]; reader.ReadStartElement(tagName); reader.ReadContentAsBinHex(result, 0, hexLength); return result; } 

usage:

 ssortingng input = "0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB255"; byte[] bytes = input.HexToBytes(2, input.Length); 

Simple:

 ssortingng hexnum = "0000000F"; // Represents 15 int value = int.Parse(hexnum, System.Globalization.NumberStyles.HexNumber); 

Tout ce que vous avez à faire est de diviser le nombre hexadécimal par un entier en groupes de 8 chiffres hexadécimaux (les caractères hexadécimaux sont de 4 bits chacun et le type de caractères CLR int est de 32 bits, soit 8 chiffres par int). Il existe également un byte.Parse () qui fonctionne de la même manière, mais passe deux chiffres hexadécimaux à la fois.

Quelque chose comme ça:

  public byte[] ParseHexSsortingng(ssortingng text) { if ((text.Length % 2) != 0) { throw new ArgumentException("Invalid length: " + text.Length); } if (text.StartsWith("0x", SsortingngComparison.InvariantCultureIgnoreCase)) { text = text.Subssortingng(2); } int arrayLength = text.Length / 2; byte[] byteArray = new byte[arrayLength]; for (int i = 0; i < arrayLength; i++) { byteArray[i] = byte.Parse(text.Substring(i*2, 2), NumberStyles.HexNumber); } return byteArray; } 

Vous devrez le modifier un peu (par exemple, ignorer les deux premiers caractères), mais cela gérera les espaces dans la chaîne:

  ///  /// Decodes a hex ssortingng, ignoring all non-hex characters, and stores /// the decodes series of bytes into the shared buffer. This returns /// the number of bytes that were decoded. /// Hex characters are [0-9, af, AF]. ///  /// Ssortingng to parse into bytes. /// Buffer into which to store the decoded binary data. /// The number of bytes decoded. private static int DecodeHexIntoBuffer(ssortingng hexSsortingng, byte[] buffer) { int count = 0; bool haveFirst = false; bool haveSecond = false; char first = '0'; char second = '0'; for (int i = 0; i < hexString.Length; i++) { if (!haveFirst) { first = hexString[i]; haveFirst = char.IsLetterOrDigit(first); // we have to continue to the next iteration // or we will miss characters continue; } if (!haveSecond) { second = hexString[i]; haveSecond = char.IsLetterOrDigit(second); } if (haveFirst && haveSecond) { string hex = "" + first + second; byte nextByte; if (byte.TryParse(hex, NumberStyles.HexNumber, null, out nextByte)) { // store the decoded byte into the next slot of the buffer buffer[count++] = nextByte; } // reset the flags haveFirst = haveSecond = false; } } return count; } 

Manière lente mais amusante: D

 public static byte[] SsortingngToByteArray(ssortingng hex) { hex = hex.Replace(" ", ""); hex = hex.Replace(":", ""); return Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(hex.Subssortingng(x, 2), 16)) .ToArray(); } 

-jD

En fait, il existe un moyen plus simple de convertir deux caractères à la fois en octet:

  ///  /// This will convert a hex-encoded ssortingng to byte data ///  /// The hex-encoded ssortingng to convert /// The bytes that make up the hex ssortingng public static byte[] FromHex(ssortingng hexData) { List data = new List(); ssortingng byteSet = ssortingng.Empty; int ssortingngLen = hexData.Length; int length = 0; for (int i = 0; i < stringLen; i = i + 2) { length = (stringLen - i) > 1 ? 2 : 1; byteSet = hexData.Subssortingng(i, length); // try and parse the data data.Add(Convert.ToByte(byteSet, 16 /*base*/)); } // next set return data.ToArray(); } 

J’utilise ceci pour C #, à partir d’un code similaire en Java.

  private static char[] hexdigit = "0123456789abcdef".ToCharArray(); public static ssortingng hexlify(ssortingng argbuf) { int arglen = argbuf.Length; char[] argca = argbuf.ToCharArray (); SsortingngBuilder retbuf = new SsortingngBuilder(arglen * 2); for (int i = 0; i < arglen; i++) { char ch = argca[i]; retbuf.Append(hexdigit[(ch >> 4) & 0xF]); retbuf.Append(hexdigit[ch & 0xF]); } return retbuf.ToSsortingng(); } public static ssortingng unhexlify(ssortingng argbuf) { int arglen = argbuf.Length; if (arglen % 2 != 0) { throw new ArgumentOutOfRangeException ("Odd-length ssortingng"); } char[] argca = argbuf.ToCharArray (); SsortingngBuilder retbuf = new SsortingngBuilder(arglen / 2); for (int i = 0; i < arglen; i += 2) { int top = Convert.ToInt32 (argca[i].ToString (), 16); int bot = Convert.ToInt32 (argca[i + 1].ToString (), 16); if (top == -1 || bot == -1) { throw new ArgumentOutOfRangeException ("Non-hexadecimal digit found"); } retbuf.Append((char) ((top << 4) + bot)); } return retbuf.ToString(); }