سؤال

وأنا نسخ ولصق هذه البيانات الثنائية من مزود خدمة، وأنا غير قادر على الاستعلام في هذا الوقت.

0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB25507EBFCD5223B

وكيف يمكنني تحويله مرة أخرى إلى صفيف بايت في ج #؟

هل كانت مفيدة؟

المحلول

وشيء من هذا القبيل:

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

و(تحرير: الآن قليلا أكثر كفاءة - لا فرعية المطلوبة ...)

ومن الممكن أن ParseNybble يمكن أن يكون أكثر كفاءة. على سبيل المثال، التبديل / حالة قد تكون أكثر كفاءة:

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

وأو ربما مجموعة البحث:

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

وأنا لم قياسها أي من هذه، وليس لدي فكرة من شأنها أن تكون أسرع. الحل الحالي هو على الارجح أبسط بالرغم من ذلك.

نصائح أخرى

والنظر في الاستفادة من فئة الإطار الذي يعرض بالفعل القدرة على تنفيذ تحويل عرافة، 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;
}

والاستعمال:

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

وبسيط:

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

وكل ما عليك القيام به هو تذكر لعدد صحيح لتقسيم عدد عرافة إلى مجموعات من 8 أرقام ست عشرية (عرافة هي 4 بت لكل منهما، ونوع CLR كثافة العمليات هو 32 بت، وبالتالي من 8 أرقام في كثافة العمليات). وهناك أيضا byte.Parse () الذي يعمل نفسه، ولكن تمر في رقمين عرافة في وقت واحد.

وشيء من هذا القبيل:

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

وسوف تحتاج إلى تعديل هذا قليلا (على سبيل المثال، تجاوز أول حرفين)، ولكنه تعامل مع مسافات في سلسلة:

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

وسيلة بطيئة ولكنها متعة: 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

في الواقع، هناك طريقة أسهل لتحويل حرفين في وقت لبايت:

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

وأنا استخدم هذا لC #، من رمز مشابهة في جاوة.

    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();
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top