CRC32带有java中的带符号字节

时间:2015-02-09 08:23:24

标签: java c crc32

我正在尝试将C CRC32代码转换为java。下面的代码是我提出的。但它似乎有所不同。在C中计算的预期CRC32是13 82 D8 46)但是下面代码的输出是“最终crc是-2084771805,以十六进制ffffffff83bce823”。有人可以告诉我为什么吗?

C代码

uint32 crc32_update(uint32 crc, const uint8_t *data, uint16 data_len)
{

uint16_t tbl_idx;

while (data_len--) {
    tbl_idx = crc ^ (*data >> (0 * 4));
    crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);
    tbl_idx = crc ^ (*data >> (1 * 4));
    crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);

    data++;
}
return crc & 0xffffffff;
}

JAVA代码。

public class crc32trial_3 {


static  final  long crc_table[] = new long[] {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};



public static long crc32_init()
{
    return 0xffffffff;
}

private static  long crc32_update(long crc, byte[] data, int data_len)
 {
     int tbl_idx;

    for(int i = 0 ; i <  data_len ; i ++) {
         tbl_idx = (int)crc ^ (data[i] >> (0 * 4));
         crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);
         tbl_idx = (int)crc ^ (data[i] >> (1 * 4));
         crc = crc_table[tbl_idx & 0x0f] ^ (crc >> 4);

         //data++;
     }

     return crc & 0xffffffff;

 }



 public static void main(String args[])
 {
     long intialcrc = crc32_init();
     long crc;


     System.out.println("the intail crc = " + intialcrc);
     byte[] packets = new byte[]{ 88,0,1,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,1,0,0,0,-1,-1,-1,-1,0,0,-56,-46,-117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-68,118 };

     byte[] totalLenght = new byte[]{100,0,0,0};
     byte[] totalSettingBlock = new byte[]{2};
      crc = crc32_update(intialcrc,totalLenght,4);
      crc = crc32_update(crc, totalSettingBlock,1);
      int temp = 28 + 72;
      crc = crc32_update(crc,packets, temp);
      long finalcrc = crc;




     System.out.println(" the final crc is " + finalcrc + "  in hex " +  Long.toHexString(finalcrc));

 }


}

2 个答案:

答案 0 :(得分:1)

你需要&#34; L&#34;在所有十六进制常量的末尾。然后我得到46d81382作为结果,这是接近,但是你所说的预期的排列。

答案 1 :(得分:0)

首先,C和Java中的>>运算符并不完全相同。 &gt;&gt;在Java中只定义了int和long类型,并且它的总是一个带符号的移位,与C相对,如果左手表达式是无符号的,则无符号的移位是无符号的。 Java中的usigned移位运算符是>>>。因此,在翻译C {#1}}时,在Java中它变为usigned >> n

其次,因为&gt;&gt; (和&gt;&gt;&gt;)存在用于int和long在Java中,在signed >>> n这样的表达式中,该字节经过扩展转换为int first ,并且当字节被签名时,它意味着符号扩展到int,而在C字节中是无符号的,这意味着它们的扩展转换也是无符号的。因此,如果要将字节视为无符号,则必须将其显式转换为unsigned int(通常称为字节屏蔽):(byte) >> 4

我不知道为什么你选择将CRC和表声明为 long ,其中 int 就足够了。

相应地更改代码会给出:

int usigned = (byte expression) & 0xFF;

运行它会给出:

public class crctrial3 { static final int crc_table[] = new int[] { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; public static int crc32_init() { return 0xffffffff; } private static int crc32_update(int crc, byte[] data, int data_len) { int tbl_idx; for (int i = 0; i < data_len; i++) { // proper byte masking and shift semantics tbl_idx = crc ^ ((data[i] & 0xFF) >>> (0 * 4)); crc = crc_table[tbl_idx & 0x0f] ^ (crc >>> 4); tbl_idx = (int) crc ^ ((data[i] & 0xFF) >>> (1 * 4)); crc = crc_table[tbl_idx & 0x0f] ^ (crc >>> 4); // data++; } return crc & 0xffffffff; } public static void main(String args[]) { int intialcrc = crc32_init(); int crc; System.out.println("the intail crc = " + intialcrc); byte[] packets = new byte[] { 88, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 1, 0, 0, 0, -1, -1, -1, -1, 0, 0, -56, -46, -117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -68, 118 }; byte[] totalLenght = new byte[] { 100, 0, 0, 0 }; byte[] totalSettingBlock = new byte[] { 2 }; crc = crc32_update(intialcrc, totalLenght, 4); crc = crc32_update(crc, totalSettingBlock, 1); int temp = 28 + 72; crc = crc32_update(crc, packets, temp); int finalcrc = crc; System.out.println(" the final crc is " + finalcrc + " in hex " + Integer.toHexString(finalcrc)); } }

看起来字节顺序不匹配,而不知道你用来到你的代码的那个代码是无法解决问题所在。由于13 82 D8 46不是简单的字节顺序反转46 D8 13 82我怀疑你原来只是误读或错误输入