10 Stimmen

Wie konvertiert man Hex in ein Byte-Array?

Ich habe diese Binärdaten aus dem Sql-Server kopiert und eingefügt, die ich derzeit nicht abfragen kann.

0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB25507EBFCD5223B

Wie konvertiere ich es zurück in ein Byte-Array in c#?

22voto

Jon Skeet Punkte 1325502

Etwa so:

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: Jetzt etwas effizienter - keine Teilstrings erforderlich...)

Es ist möglich, dass ParseNybble effizienter sein könnte. Zum Beispiel, ein Schalter/Gehäuse Mai effizienter sein:

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

oder möglicherweise ein Lookup-Array:

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

Ich habe keine dieser Geräte getestet und weiß nicht, welches das schnellste ist. Die derzeitige Lösung ist aber wahrscheinlich die einfachste.

6voto

Handcraftsman Punkte 6635

Ziehen Sie in Erwägung, eine Framework-Klasse zu nutzen, die bereits die Möglichkeit bietet, eine Hex-Konvertierung durchzuführen, z. B. XmlReader:

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

Verwendung:

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

4voto

Kevin Anderson Punkte 6411

Einfach:

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

Alles, was Sie sich merken müssen, ist, dass ein int die Hex-Zahl in Gruppen von 8 Hex-Ziffern aufteilt (Hex sind jeweils 4 Bits, und der CLR int-Typ ist 32 Bits, also 8 Ziffern pro int). Es gibt auch ein byte.Parse(), das genauso funktioniert, aber zwei Hex-Ziffern auf einmal übergibt.

3voto

MatteKarla Punkte 2667

Etwa so:

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

1voto

Erich Mirabal Punkte 9642

Sie müssen dies ein wenig abändern (z. B. die ersten beiden Zeichen überspringen), aber es behandelt Leerzeichen in der Zeichenkette:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X