Question

Je copié et collé ces données binaires sur SQL Server, que je suis incapable d'interroger à ce moment.

0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB25507EBFCD5223B

Comment puis-je reconvertir en un tableau d'octets en C #?

Était-ce utile?

La solution

Quelque chose comme ceci:

using System;

public static class Parser
{    
    static void Main()
    {
        string hex = "0xBAC893CAB8B7FE03C927417A2A3F6A6"
                     + "0BD30FF35E250011CB25507EBFCD5223B";
        byte[] parsed = ParseHex(hex);
        // Just for confirmation...
        Console.WriteLine(BitConverter.ToString(parsed));
    }

    public static byte[] ParseHex(string 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: Maintenant, un peu plus efficace - pas nécessaire ... substrings)

Il est possible que pourrait être plus ParseNybble efficace. Par exemple, un commutateur / cas 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 pas benchmarkée toutes ces choses, et je n'ai aucune idée qui serait le plus rapide. La solution actuelle est probablement la plus simple cependant.

Autres conseils

Envisager une classe tirant parti-cadre qui expose déjà la possibilité d'effectuer la conversion hexadécimal, XmlReader par exemple:

public static byte[] HexToBytes(this string hexEncodedBytes, int start, int end)
{
    int length = end - start;
    const string tagName = "hex";
    string fakeXmlDocument = String.Format("<{1}>{0}</{1}>",
                           hexEncodedBytes.Substring(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;
}

utilisation:

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

simple:

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

Tout ce que vous devez vous rappeler de faire est un entier de diviser le nombre hexadécimal en groupes de 8 chiffres hexadécimaux (hex sont 4 bits chacun, et le type int CLR est de 32 bits, donc 8 chiffres par int). Il y a aussi un byte.Parse () qui fonctionne de la même, mais ils passent en deux chiffres hexadécimaux à la fois.

Quelque chose comme ceci:

    public byte[] ParseHexString(string text)
    {
        if ((text.Length % 2) != 0)
        {
            throw new ArgumentException("Invalid length: " + text.Length);
        }

        if (text.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
        {
            text = text.Substring(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 devez modifier un peu cette question (par exemple, sauter les deux premiers caractères), mais il ne gère des espaces dans la chaîne:

    /// <summary>
    /// Decodes a hex string, 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.
    /// <para>Hex characters are [0-9, a-f, A-F].</para>
    /// </summary>
    /// <param name="hexString">String to parse into bytes.</param>
    /// <param name="buffer">Buffer into which to store the decoded binary data.</param>
    /// <returns>The number of bytes decoded.</returns>
    private static int DecodeHexIntoBuffer(string hexString, 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;
    }

façon lente mais amusant: D

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

-JD

En fait, il y a un moyen plus facile de convertir deux caractères à la fois à un octet:

    /// <summary>
    /// This will convert a hex-encoded string to byte data
    /// </summary>
    /// <param name="hexData">The hex-encoded string to convert</param>
    /// <returns>The bytes that make up the hex string</returns>
    public static byte[] FromHex(string hexData)
    {
        List<byte> data = new List<byte>();
        string byteSet = string.Empty;
        int stringLen = hexData.Length;
        int length = 0;
        for (int i = 0; i < stringLen; i = i + 2)
        {
            length = (stringLen - i) > 1 ? 2 : 1;
            byteSet = hexData.Substring(i, length);

            // try and parse the data
            data.Add(Convert.ToByte(byteSet, 16 /*base*/));
        } // next set

        return data.ToArray();
    }

J'utilise cela pour C #, à partir du code similaire à Java.

    private static char[] hexdigit = "0123456789abcdef".ToCharArray();

    public static string hexlify(string argbuf) {
        int arglen = argbuf.Length;
        char[] argca = argbuf.ToCharArray ();
        StringBuilder retbuf = new StringBuilder(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.ToString();
    }

    public static string unhexlify(string argbuf) {
        int arglen = argbuf.Length;
        if (arglen % 2 != 0) {
            throw new ArgumentOutOfRangeException ("Odd-length string");
        }
        char[] argca = argbuf.ToCharArray ();
        StringBuilder retbuf = new StringBuilder(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();
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top