ascii byte []和int之间的直接转换

时间:2016-03-29 22:04:58

标签: c# parsing binary bytearray

我有一个从网络中读取字节的程序。有时,这些字节是十进制或十六进制形式的整数字符串表示。

通常,我用

之类的东西解析它
var s=Encoding.ASCII.GetString(p.GetBuffer(),0,(int)p.Length);                                      
int.TryParse(s, out number);

我觉得这很浪费,因为它必须在没有任何需要的情况下为字符串分配内存。

在c#中有更好的方法吗?

更新

我见过几个使用BitConverter课程的建议。这不是我需要的。 BitConverter会将int(4字节)的二进制表示转换为int类型,但由于int是ascii形式,因此这里不适用。

2 个答案:

答案 0 :(得分:3)

我怀疑它会对性能或内存消耗产生重大影响,但你可以相对容易地做到这一点。转换十进制数的一种实现如下所示:

private static int IntFromDecimalAscii(byte[] bytes)
{
    int result = 0;

    // For each digit, add the digit's value times 10^n, where n is the
    // column number counting from right to left starting at 0.
    for(int i = 0; i < bytes.Length; ++i)
    {
        // ASCII digits are in the range 48 <= n <= 57. This code only
        // makes sense if we are dealing exclusively with digits, so
        // throw if we encounter a non-digit character
        if(bytes[i] < 48 || bytes[i] > 57)
        {
            throw new ArgumentException("Non-digit character present", "bytes");
        }

        // The bytes are in order from most to least significant, so
        // we need to reverse the index to get the right column number
        int exp = bytes.Length - i - 1;

        // Digits in ASCII start with 0 at 48, and move sequentially
        // to 9 at 57, so we can simply subtract 48 from a valid digit
        // to get its numeric value
        int digitValue = bytes[i] - 48;

        // Finally, add the digit value times the column value to the
        // result accumulator
        result += digitValue * (int)Math.Pow(10, exp);
    }

    return result;
}

这也很容易适用于转换十六进制值:

private static int IntFromHexAscii(byte[] bytes)
{
    int result = 0;
    for(int i = 0; i < bytes.Length; ++i)
    {
        // ASCII hex digits are a bit more complex than decimal.
        if(bytes[i] < 48 || bytes[i] > 71 || (bytes[i] > 57 && bytes[i] < 65))
        {
            throw new ArgumentException("Non-digit character present", "bytes");
        }
        int exp = bytes.Length - i - 1;

        // Assume decimal first, then fix it if it's actually hex.
        int digitValue = bytes[i] - 48;
        // This is safe because we already excluded all non-digit
        // characters above
        if(bytes[i] > 57) // A-F
        {
            digitValue = bytes[i] - 55;
        }

        // For hex, we use 16^n instead of 10^n
        result += digitValue * (int)Math.Pow(16, exp);
    }

    return result;
}

答案 1 :(得分:0)

嗯,通过避免像以下声明的声明,你可能会少一点浪费(至少在源代码字符意义上的数量):

int.TryParse(Encoding.ASCII.GetString(p.GetBuffer(),0,(int)p.Length), out number);

但是,我认为获得加速的唯一其他方法是按照评论者的建议去做,并硬编码映射到字典或其他东西。如果你不得不这么做,这可以节省一些时间,但这可能不值得努力......