Java 相当于 C CRC16
Java equivalent for C CRC16
我需要将 C
CRC16 方法转换为 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;
}
这个returns十进制值。而且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;
}
为了测试您的结果,您可以使用 this site(感谢@greenaps)
你写的和 Mohit Jain 说的一样好。但是你的函数做的事情与原来的 C 函数不同:你接受一个字符串数组,而 C 代码接受一个 void * 和一个以字节为单位的长度。因此,如果您使用转换函数在 UTF-8 和 Latin1 平台之间验证包含非 ASCII 字符的字符串,它将给出不同的结果,因为对于 Latin1,“éè”将给出 2 个字节 0xe9
,0xe8
,而使用 UTF-8,您将得到 4 个字节:0xc3
、0xa9
、0xc3
、0xa8
=> 您的 CRC 函数将给出不同的结果。
恕我直言,您应该坚持使用原始代码,只为字节数组计算 CRC。您可以强制始终使用相同的字符集(例如 UTF-8),但仍然很难将您的结果与 C 实现进行比较,并且您将失去计算原始字节数组(二进制数据)的 CRC 的能力。
无论如何,确保您的实现给出与原始 C 实现相同结果的唯一方法是采用任意字节字符串(例如从 0 到 255 的所有字节),将其传递给其中一个上的 C 例程一边和你 java 一个在另一边并比较两个 CRC。
你翻译的c代码函数调用crc16 (const void *data, unsigned data_size)
错了。
public static int getCode (String[] data)
应该是
public static int getCode (String data)
此外,您还可以在 Wialon pdf 中看到您需要 getCode (String)
而不是 getCode(String[])
。
将接收到的字符串转换为字节数组。
我需要将 C
CRC16 方法转换为 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;
}
这个returns十进制值。而且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;
}
为了测试您的结果,您可以使用 this site(感谢@greenaps)
你写的和 Mohit Jain 说的一样好。但是你的函数做的事情与原来的 C 函数不同:你接受一个字符串数组,而 C 代码接受一个 void * 和一个以字节为单位的长度。因此,如果您使用转换函数在 UTF-8 和 Latin1 平台之间验证包含非 ASCII 字符的字符串,它将给出不同的结果,因为对于 Latin1,“éè”将给出 2 个字节 0xe9
,0xe8
,而使用 UTF-8,您将得到 4 个字节:0xc3
、0xa9
、0xc3
、0xa8
=> 您的 CRC 函数将给出不同的结果。
恕我直言,您应该坚持使用原始代码,只为字节数组计算 CRC。您可以强制始终使用相同的字符集(例如 UTF-8),但仍然很难将您的结果与 C 实现进行比较,并且您将失去计算原始字节数组(二进制数据)的 CRC 的能力。
无论如何,确保您的实现给出与原始 C 实现相同结果的唯一方法是采用任意字节字符串(例如从 0 到 255 的所有字节),将其传递给其中一个上的 C 例程一边和你 java 一个在另一边并比较两个 CRC。
你翻译的c代码函数调用crc16 (const void *data, unsigned data_size)
错了。
public static int getCode (String[] data)
应该是
public static int getCode (String data)
此外,您还可以在 Wialon pdf 中看到您需要 getCode (String)
而不是 getCode(String[])
。
将接收到的字符串转换为字节数组。