计算十六进制字符串的二进制补码校验和



我有一个字符串" 0AAE000000463130004144430000",我需要计算两种组成字符串的十六进制字节的补充检查。

上面示例字符串的公式是

  1. 总和值:0a ae 00 00 00 46 31 30 00 00 41 44 43 00 00 = 27(丢弃溢出)
  2. 从0x100 = 0xD9
  3. 减去结果

d9是此示例的正确校验和,但是我很难从C#中的字符串中删除两个数字的十六进制值。我当前的代码如下:

string output = "0AAE0000463130004144430000";
long checksum = 0;
char[] outputBytes = output.TrimStart(':').ToCharArray();
foreach (var outputByte in outputBytes)
{
    checksum += Convert.ToInt32(outputByte);
    checksum = checksum & 0xFF;
}
checksum = 256 - checksum;

然而,这是据我所知的ASCII值,并为每个字符做。

您可以在system.runtime.remoting.metadata.w3cxsd2001中使用SoapHexBinary类。

soapHexBinary.Value属性将返回您一个字节数组

string hexString = "0AAE0000463130004144430000";
byte[] buf = SoapHexBinary.Parse(hexString).Value;
int chkSum = buf.Aggregate(0, (s, b) => s += b) & 0xff;
chkSum = (0x100 - chkSum) & 0xff;
var str = chkSum.ToString("X2"); // <-- D9

试试看。一次使用substring抓住两个字符,并使用numberstyles.allowhexspecifier。

string output = "0AAE0000463130004144430000";
int checksum = 0;
// You'll need to add error checking that the string only contains [0-9A-F], 
// is an even number of characters, etc.
for(int i = 0; i < output.length; i+=2)
{
   int value = int.Parse(output.SubString(i, 2), NumberStyles.AllowHexSpecifier);
   checksum = (checksum + value) & 0xFF;
}
checksum = 256 - checksum;

如果要包含System.Runtime.Remoting.Metadata.W3cXsd2001名称空间,则可以接受的答案有效。

如果您不想包括名称空间,则以下代码将返回正确的结果。此示例和上面示例之间的区别是添加到返回值中的附加& 0xFF。没有这个,在计算所有零零的校验和时,您的结果将不正确。

public static class ExtensionMethods
{
    public static string MicrochipDataString(this string input)
    {
        int TwosComplement(string s)
        {
            if (s.Length % 2 != 0)
                throw new FormatException(nameof(input));
            var checksum = 0;
            for (var i = 0; i < s.Length; i += 2)
            {
                var value = int.Parse(s.Substring(i, 2), NumberStyles.AllowHexSpecifier);
                checksum = (checksum + value) & 0xFF;
            }
            return 256 - checksum & 0xFF;
        }
        return string.Concat(":", input, TwosComplement(input).ToString("X2"));
    }
}

最新更新