将C ++ Checksum函数转换为Java

时间:2012-12-12 11:48:39

标签: java c++ checksum

我正在尝试将此C ++校验和转换为Java,但暂时我失败了。我做错了什么?

该怎么办? 它应该在OpenGL

中返回缓冲区的正校验和

这是C部分。

DWORD QuickChecksum(DWORD *data, int size){

if(!data) {
    return 0x0; 
}

DWORD sum;
DWORD tmp;
sum = *data;

for(int i = 1; i < (size/4); i++)
{
    tmp = data[i];
    tmp = (DWORD)(sum >> 29) + tmp;
    tmp = (DWORD)(sum >> 17) + tmp;
    sum = (DWORD)(sum << 3)  ^ tmp;
}

return sum;
}

以下是我在Java中尝试过的内容。据我所知,DWORD是32位所以我在一个long中使用int得到一个unsigned int,这应该在java中使用&gt;&gt;&gt;?

我一直在看这个问题,因为我已经对它视而不见了。

public static long getChecksum(byte[] data, int size) {
    long sum, tmp;
    sum = getInt(new byte[]{data[0], data[1], data[2], data[3]},true) & 0xFF;
    for(int I = 4; I < data.length; I += 4)
    {
        tmp = getInt(new byte[]{data[I],data[I+1],data[I+2],data[I+3]},true) & 0xFF;
        tmp = (sum >>> 29) + tmp;
        tmp = (sum >>> 17) + tmp;
        sum = (sum << 3) ^ tmp;
    }
    return sum & 0xFF;
}

private static int getInt(byte[] bytes, boolean big) {
    ByteBuffer bb = ByteBuffer.wrap(bytes);
    return bb.getInt();
}

谢谢大家的帮助!

3 个答案:

答案 0 :(得分:1)

明显的错误是,在三个地方,你和输入字以及最后的校验和0xff,丢失了高24位。据推测,您正在尝试将long值减少到32位,这需要AND与0xffffffffL。在执行此操作之前,您还需要将getInt()的返回值转换为long,否则您仍会获得您要避免的符号扩展名。

我的Java有点生疏,但我相当肯定只要你使用int进行右移,你就可以坚持>>>得到正确的结果(就像你一样)做)。

你也有一个错误,你无条件地读取前四个字节而不检查输入是否为空。

您还需要确保输入具有4个字节的倍数;要么通过检查长度,要么通过更改它来使用int[]而不是{C}版本的byte[]。当然,不需要size参数,因为Java数组随身携带它们的大小。

以下内容应与C版本具有相同的结果:

public static int checksum(int[] data)
{
    if (data.length == 0) {
        return 0;
    }

    int sum = data[0];
    for (int i = 1; i < data.length; ++i) {
        int tmp = data[i];
        tmp = (sum >>> 29) + tmp;
        tmp = (sum >>> 17) + tmp;
        sum = (sum << 3)   ^ tmp;
    }

    return sum;
}

答案 1 :(得分:0)

在Java中,>>>执行无符号移位,这意味着它会将位值0插入到移入的新位中,将负数转换为正数。有符号移位>>扩展符号位,负值为1,因此负数保持为负数。

要修复您的代码,请至少将0xFF替换为&amp;中的0xFFFFFFFF。操作。此外,我认为您每次分配到tmpsum时都可能必须这样做,而不是仅仅在循环后一次(不是100%肯定,必须通过代码查看是否正确)比特得到保留,即使没有ANDing也没有额外的位潜入,所以比抱歉更安全。

我还在方法中首先添加:

if (data.length & 3 != 0) 
    throw new IllegalArgumentException("byte buffer size not multiple of 4");

此外,我要么删除size参数,要么实际使用它而不是data.length(在检查它有效之后),以防数据可能包含比您想要处理的更多的字节。

答案 2 :(得分:0)

C ++版本返回sum的32位,但您的Java版本只有& 0xFF,只剩下8位。

  1. 使用>>>执行无符号移位,并定义所有其他操作,以便它们在签名Java类型中的结果等于C ++无符号类型上的相同操作,除了对有符号位的解释。所以你可以在这里使用int
  2. 如果您继续使用long,则需要使用& 0xFFFFFFFF获取32位。