校验和UTF-8字符串

时间:2017-08-10 01:36:06

标签: c# encoding utf-8

以下是校验和说明。 校验和是四个ASCII字符数字,表示字符的二进制和,包括 传输的第一个字符,直到并包括校验和字段标识符字符。 要计算校验和,请将每个字符添加为无符号二进制数,取下的16位 总计并执行2的补充。校验和字段是由四个十六进制数字表示的结果。 要验证接收数据的正确校验和,只需添加所有十六进制值,包括校验和。它 应该等于零。

这是ASCII字符串的实现,但我的输入字符串现在是UTF-8。 有人提出修改UTF-8编码实现的想法。非常感谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SIP2
{
    //  Adapted from VB.NET from the Library Tech Guy blog
    //  http://librarytechguy.blogspot.com/2009/11/sip2-checksum_13.html

    public class CheckSum
    {
        public static string ApplyChecksum(string strMsg)
        {
            int intCtr;
            char[] chrArray;
            int intAscSum;
            bool blnCarryBit;
            string strBinVal = String.Empty;
            string strInvBinVal;
            string strNewBinVal = String.Empty;

            // Transfer SIP message to a a character array.Loop through each character of the array,
            // converting the character to an ASCII value and adding the value to a running total.

            intAscSum = 0;
            chrArray = strMsg.ToCharArray();

            for (intCtr = 0; intCtr <= chrArray.Length - 1; intCtr++)
            {
                intAscSum = intAscSum + (chrArray[intCtr]);
            }

            // Next, convert ASCII sum to a binary digit by: 
            // 1) taking the remainder of the ASCII sum divided by 2 
            // 2) Repeat until sum reaches 0 
            // 3) Pad to 16 digits with leading zeroes 

            do
            {
                strBinVal = (intAscSum % 2).ToString() + strBinVal;
                intAscSum = intAscSum / 2;
            } while (intAscSum > 0);

            strBinVal = strBinVal.PadLeft(16, '0');

            // Next, invert all bits in binary number. 
            chrArray = strBinVal.ToCharArray();
            strInvBinVal = "";

            for (intCtr = 0; intCtr <= chrArray.Length - 1; intCtr++)
            {
                if (chrArray[intCtr] == '0') { strInvBinVal = strInvBinVal + '1'; }
                else { strInvBinVal = strInvBinVal + '0'; }
            }


            // Next, add 1 to the inverted binary digit. Loop from least significant digit (rightmost) to most (leftmost); 
            // if digit is 1, flip to 0 and retain carry bit to next significant digit. 

            blnCarryBit = true;
            chrArray = strInvBinVal.ToCharArray();

            for (intCtr = chrArray.Length - 1; intCtr >= 0; intCtr--)
            {
                if (blnCarryBit == true)
                {
                    if (chrArray[intCtr] == '0')
                    {
                        chrArray[intCtr] = '1';
                        blnCarryBit = false;
                    }
                    else
                    {
                        chrArray[intCtr] = '0';
                        blnCarryBit = true;
                    }
                }
                strNewBinVal = chrArray[intCtr] + strNewBinVal;
            }

            // Finally, convert binary digit to hex value, append to original SIP message. 
            return strMsg + (Convert.ToInt16(strNewBinVal, 2)).ToString("X");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

替换代码

for (intCtr = 0; intCtr <= chrArray.Length - 1; intCtr++)
{
    intAscSum = intAscSum + (chrArray[intCtr]); 
}

chrArray[intCtr]是输入ASCII字符串以输出十进制的ASCII码,例如&#34; A&#34;是65. ASCII编码只使用1个字节。 UTF-8使用一个字节或多个字节来表示UTF-8字符。我认为chrArray[intCtr]是针对ASCII设计的 - 因此输入UTF-8(超过一个字节)是不合理的。

使用

int i = 0;
for (i = 0; i < bytes.Length; i++)
{
    intAscSum = intAscSum + bytes[i];
}
byte[] bytes = Encoding.UTF8.GetBytes(strMsg); 

添加所有字节,因为一个UTF8字符可以多于一个字节。