【问题标题】:Java checksum calculation for serial comunication串行通信的Java校验和计算
【发布时间】:2014-08-07 16:35:13
【问题描述】:

我在 Java 中有这段代码:

public static synchronized String generarCheckSum(int campoInicio, String comando, boolean tieneCheckSum)
{
    String checkSum = "";
    int leerHasta = 1;
    if(tieneCheckSum)
        leerHasta = 3;
    int suma = campoInicio;
    int idxInicio = 0;
    try
    {
        if(!es3600(comando))
        {
            idxInicio = 1;
            for(int i = 0; i < TIPO_EQUIPO.length; i++)
                if(TIPO_EQUIPO[i].equals(comando.substring(0, 1)))
                    suma = suma + 65 + i;

        }
        for(int i = idxInicio; i <= comando.length() - leerHasta; i++)
        {
            if(comando.charAt(i) == '\n')
                continue;
            if(comando.charAt(i) == '\u20AC')
                suma += 128;
            else
                suma += comando.charAt(i);
        }

        String sumaStr = Integer.toHexString(suma);
        sumaStr = sumaStr.substring(sumaStr.length() - 2, sumaStr.length());
        String Eh = (new StringBuilder()).append("3").append(sumaStr.charAt(0)).toString();
        String El = (new StringBuilder()).append("3").append(sumaStr.charAt(1)).toString();
        checkSum = (new StringBuilder()).append(UtlGeneral.convertirHexaToASCII(Eh)).append(UtlGeneral.convertirHexaToASCII(El)).toString();
    }
    catch(Exception e)
    {
        return null;
    }
    return checkSum;
}

例如这样调用:

chk = generarCheckSum(2, comando, false)

我不懂 Java,所以很难理解代码的作用。据我所知,它是从一个字符串中计算一个两字节的校验和。

我有这个十六进制字符串的例子:

07303131393904
07303232393B04
07303332393C04
073235323A3004

在这一行中,唯一改变的是设备编号:01、02、03 和 25

我猜第一个和最后一个字节是分隔符:07 和 04,而 3939、393B、393C 和 3A30 是计算出来的校验和。

在我的情况下,es3600 检查返回 TRUE,因为设备是 3600 型号。

校验和计算的算法是什么?

编辑:更多信息。

在另一个示例中:

02 30 33 33 34 30 33 30 32 30 31 30 34 30 35 30 36 32 31 04

将所有数字相加 = 321(十六进制)所以结果是 32 31(仅使用 321 的最后 2 位) 非常奇怪的校验和方式...

【问题讨论】:

  • 如果s是一个字符串,s.charAt(n)返回第n的字符,从0开始,即s.charAt(0)是第一个字符,s.charAt(1)是第二个字符,以此类推. s.substring(0,1) 返回一个长度为 1 个字符的 String,使用与 s.charAt(0) 相同的字符。 EhEl 基本上设置为第一个字符为 '3' 的 2 个字符的字符串。分配给sumaStr 的最后一行将其分配给前一个sumaStr 的最后两个字符。
  • 我或多或少明白这一点。似乎添加“charAt”会将字符的ascii hex值添加到suma。
  • 我或多或少知道在做什么,我认为他们正在以一种非常复杂的方式计算校验和:正在添加每个字符的十六进制值,包括第一个字符。例如第一行是 07+30+31+31 = 99 并且它被转换为 3939 如果字符串更长并且总和大于 FF,他们使用十六进制数的最后 2 个字符,并进行拆分和添加两个“3”。很奇怪他们是如何计算这个的。
  • 对,在这种情况下Java的char类型被视为一个整数(因此字符'A'等价于整数65 = 0x41等)。
  • charAt 给出每个字符的数值,而不是十六进制值(它是一个数字,而不是字符串),它是 UTF-16BE 值,而不是 ASCII,尽管对于所有字符不是 Unicode 高半或低半代理,它将与 Unicode 代码点相同,Latin-1 是 Unicode 的子集,ASCII 是 Latin-1 的子集。

标签: java checksum


【解决方案1】:

这是我自带的(这是 Visual FoxPro)(是的,我知道)

*!* GENERARCHECKSUM

Lparameters pString

Local checksum, lnx

m.checksum = 0

For m.lnx = 1 To Len(m.pString)
    m.checksum = m.checksum + Asc(Substr(m.pString, m.lnx, 1))
Endfor

Return Chr(0x30 + Bitrshift(Bitand(m.checksum, 0xf0), 4)) + Chr(0x30 + Bitand(m.checksum, 0x0f))

【讨论】:

    猜你喜欢
    • 2010-10-27
    • 2015-07-03
    • 2015-06-05
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多