1

我需要将CCRC16 方法转换为Java. 问题是我不太擅长C和字节操作。

C代码:

static const unsigned short crc16_table[256] =
{
 0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
 ...  /* Removed for brevity */
 0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040
};

unsigned short crc16 (const void *data, unsigned data_size)
{
 if (!data || !data_size)
 return 0;
 unsigned short crc = 0;
 unsigned char* buf = (unsigned char*)data;
 while (data_size--)
 crc = (crc >> 8) ^ crc16_table[(unsigned char)crc ^ *buf++];
 return crc;
}

这就是我转换它的尝试。不确定这是否正确。

private static int[] table = {
    0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,0xC601,0x06C0,0x0780,0xC741,
    ...    // Removed for brevity
    0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,0x8201,0x42C0,0x4380,0x8341, 0x4100,0x81C1,0x8081,0x4040
};

public static int getCode (String[] data){
    if (data.length == 0) {
        return 0;
    }
    int crc = 0;
    for (String item : data) {
        byte[] bytes = item.getBytes();
        for (byte b : bytes) {
            crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff]; //this confuses me
        }
    }
    return crc;
}

问题: 我移植到 Java 是否正确?


编辑

修改后crc16的工作方法(感谢出色的答案):

public static int getCode(String data) {
    if (data == null || data.equals("")) {
        return 0;
    }
    int crc = 0x0000;
    byte[] bytes = data.getBytes();
    for (byte b : bytes) {
        crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
    }
    return crc;
}

这将返回十进制值。并且 CRC16 代码需要是十六进制的。我使用此方法转换为基数 16。使用收到的方法执行此crc操作dec2m(crc, 16)

static String dec2m(int N, int m) {
    String s = "";
    for (int n = N; n > 0; n /= m) {
        int r = n % m;
        s = r < 10 ? r + s : (char) ('A' - 10 + r) + s;
    }
    return s;
}

为了测试你的结果,你可以使用这个网站(感谢@greenaps)

4

2 回答 2

2

正如 Mohit Jain 所说,您写的内容看起来不错。但是你的函数做的事情与原来的 C 不同:你接受一个字符串数组,而 C 代码接受一个 void * 和一个以字节为单位的长度。因此,如果您使用转换函数在 UTF-8 和 Latin1 平台之间验证包含非 ASCII 字符的字符串,它将给出不同的结果,因为对于 Latin1,“éè”将给出 2 个字节0xe90xe8而对于 UTF-8 , 你会得到 4 个字节 : 0xc3, 0xa9, 0xc3, 0xa8=> 你的 CRC 函数会给出不同的结果。

恕我直言,您应该坚持使用原始代码,并且只计算字节数组的 CRC。您可以始终强制使用相同的字符集(例如 UTF-8),但仍然很难将您的结果与 C 实现进行比较,并且您将失去计算原始字节数组(二进制数据)的 CRC 的能力。

无论如何,确保您的实现提供与原始 C 相同的结果的唯一方法是采用任意字节字符串(例如,从 0 到 255 的所有字节),将其传递给一侧的 C 例程和您的 java另一侧并比较两个 CRC。

于 2015-06-17T12:28:16.890 回答
1

你翻译的c代码函数调用crc16 (const void *data, unsigned data_size)错误。

public static int getCode (String[] data)

应该

public static int getCode (String data)

此外,您还可以在 Wialon pdf 中看到您需要 agetCode (String)而不是getCode(String[]).

将接收到的字符串转换为字节数组就可以了。

于 2015-06-18T08:22:21.633 回答