Most light weight conversion from hex to byte in c

2019-01-13 02:44发布

Possible Duplicate:
How do you convert Byte Array to Hexadecimal String, and vice versa?

I need an efficient and fast way to do this conversion. I have tried two different ways, but they are not efficient enough for me. Is there any other quick method to accomplish this in a real-time fashion for an application with huge data?

  public byte[] StringToByteArray(string hex)
    {
        return Enumerable.Range(0, hex.Length / 2).Select(x => Byte.Parse(hex.Substring(2 * x, 2), NumberStyles.HexNumber)).ToArray(); 
    }

The above one felt more efficient to me.

 public static byte[] stringTobyte(string hexString)
    {
        try
        {
            int bytesCount = (hexString.Length) / 2;
            byte[] bytes = new byte[bytesCount];
            for (int x = 0; x < bytesCount; ++x)
            {
                bytes[x] = Convert.ToByte(hexString.Substring(x * 2, 2), 16);
            }
            return bytes;
        }
        catch
        {
            throw;
        }

标签: c# hex byte
3条回答
乱世女痞
2楼-- · 2019-01-13 03:19

I took the benchmarking code from the other question, and reworked it to test the hex to bytes methods given here:

HexToBytesJon: 36979.7 average ticks (over 150 runs)
HexToBytesJon2: 35886.4 average ticks (over 150 runs)
HexToBytesJonCiC: 31230.2 average ticks (over 150 runs)
HexToBytesJase: 15359.1 average ticks (over 150 runs)

HexToBytesJon is Jon's first version, and HexToBytesJon2 is the second variant. HexToBytesJonCiC is Jon's version with CodesInChaos's suggested code. HexToBytesJase is my attempt, based on both the above but with alternative nybble conversion which eschews error checking, and branching:

    public static byte[] HexToBytesJase(string hexString)
    {
        if ((hexString.Length & 1) != 0)
        {
            throw new ArgumentException("Input must have even number of characters");
        }
        byte[] ret = new byte[hexString.Length/2];
        for (int i = 0; i < ret.Length; i++)
        {
            int high = hexString[i*2];
            int low = hexString[i*2+1];
            high = (high & 0xf) + ((high & 0x40) >> 6) * 9;
            low = (low & 0xf) + ((low & 0x40) >> 6) * 9;

            ret[i] = (byte)((high << 4) | low);
        }

        return ret;
    }
查看更多
兄弟一词,经得起流年.
3楼-- · 2019-01-13 03:22

If you really need efficiency then:

  • Don't create substrings
  • Don't create an iterator

Or, and get rid of try blocks which only have a catch block which rethrows... for simplicity rather than efficiency though.

This would be a pretty efficient version:

public static byte[] ParseHex(string hexString)
{
    if ((hexString.Length & 1) != 0)
    {
        throw new ArgumentException("Input must have even number of characters");
    }
    int length = hexString.Length / 2;
    byte[] ret = new byte[length];
    for (int i = 0, j = 0; i < length; i++)
    {
        int high = ParseNybble(hexString[j++]);
        int low = ParseNybble(hexString[j++]);
        ret[i] = (byte) ((high << 4) | low);
    }

    return ret;
}

private static int ParseNybble(char c)
{
    // TODO: Benchmark using if statements instead
    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);
        default:
            throw new ArgumentException("Invalid nybble: " + c);
    }
    return c;
}

The TODO refers to an alternative like this. I haven't measured which is faster.

private static int ParseNybble(char c)
{
    if (c >= '0' && c <= '9')
    {
        return c - '0';
    }
    c = (char) (c & ~0x20);
    if (c >= 'A' && c <= 'F')
    {
        return c - ('A' - 10);
    }
    throw new ArgumentException("Invalid nybble: " + c);
}
查看更多
迷人小祖宗
4楼-- · 2019-01-13 03:32

As a variant of Jon's if based ParseNybble:

public static byte[] ParseHex(string hexString)
{
    if ((hexString.Length & 1) != 0)
    {
        throw new ArgumentException("Input must have even number of characters");
    }
    byte[] ret = new byte[hexString.Length / 2];
    for (int i = 0; i < ret.Length; i++)
    {
        int high = ParseNybble(hexString[i*2]);
        int low = ParseNybble(hexString[i*2+1]);
        ret[i] = (byte) ((high << 4) | low);
    }

    return ret;
}

private static int ParseNybble(char c)
{
    unchecked
    {
        uint i = (uint)(c - '0');
        if(i < 10)
            return (int)i;
        i = ((uint)c & ~0x20u) - 'A';
        if(i < 6)
            return (int)i+10;
        throw new ArgumentException("Invalid nybble: " + c);
    }
}
查看更多
登录 后发表回答