ascii byte[] 和 int 直接转换
Direct convertation between ascii byte[] and int
我有一个从网络读取字节的程序。有时,这些字节是以十进制或十六进制形式表示的整数字符串。
通常,我用类似
的方式解析它
var s=Encoding.ASCII.GetString(p.GetBuffer(),0,(int)p.Length);
int.TryParse(s, out number);
我觉得这很浪费,因为它必须为字符串分配内存而不需要它。
有没有更好的方法可以用 c# 实现?
更新
我看到了一些使用 BitConverter
class 的建议。这不是我需要的。 BitConverter 会将 int(4 个字节)的二进制表示形式转换为 int 类型,但由于 int 是 ascii 形式,因此这里不适用。
好吧,通过避免像这样的 s 声明,您可以减少浪费(至少在源代码字符数方面):
int.TryParse(Encoding.ASCII.GetString(p.GetBuffer(),0,(int)p.Length), out number);
但是,我认为获得加速的唯一其他真正方法是按照评论者的建议进行操作,并将映射硬编码到字典或其他内容中。如果您必须经常这样做,这可以节省一些时间,但这可能不值得付出努力...
我怀疑它会对性能或内存消耗产生重大影响,但您可以相对轻松地做到这一点。一种转换十进制数的实现如下所示:
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;
}
我有一个从网络读取字节的程序。有时,这些字节是以十进制或十六进制形式表示的整数字符串。
通常,我用类似
的方式解析它var s=Encoding.ASCII.GetString(p.GetBuffer(),0,(int)p.Length);
int.TryParse(s, out number);
我觉得这很浪费,因为它必须为字符串分配内存而不需要它。
有没有更好的方法可以用 c# 实现?
更新
我看到了一些使用 BitConverter
class 的建议。这不是我需要的。 BitConverter 会将 int(4 个字节)的二进制表示形式转换为 int 类型,但由于 int 是 ascii 形式,因此这里不适用。
好吧,通过避免像这样的 s 声明,您可以减少浪费(至少在源代码字符数方面):
int.TryParse(Encoding.ASCII.GetString(p.GetBuffer(),0,(int)p.Length), out number);
但是,我认为获得加速的唯一其他真正方法是按照评论者的建议进行操作,并将映射硬编码到字典或其他内容中。如果您必须经常这样做,这可以节省一些时间,但这可能不值得付出努力...
我怀疑它会对性能或内存消耗产生重大影响,但您可以相对轻松地做到这一点。一种转换十进制数的实现如下所示:
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;
}