如何将此校验和代码从C#转换为Java?

时间:2011-12-01 19:36:31

标签: c# java

我需要帮助将此代码从C#转换为Java。

    public static ulong GetChecksum(byte[] data)
    {
        ulong sum = 0;
        foreach (var item in data)
            sum += item;

        return ulong.MaxValue - sum + 1;
    }

Java版本将返回long,而不是ulong。

编辑:我没有尝试过任何东西,因为我不知道如何处理最后一行ulong.MaxValue。基本上,我需要的最终结果是产生与C#中的(long)GetChecksum(缓冲区)相同的数字,与java中的getChecksum(缓冲区)相同。 我是java的新手,这就是我问这个的原因。

Edit2:这是最终的解决方案。许多有用的评论。谢谢你们。

public static byte[] getChecksum(byte[] data) {
        BigInteger sum = BigInteger.ZERO;
        for (byte s : data)
            sum = sum.add(BigInteger.valueOf((long) ((char) s & 0xFF)));

        return new BigInteger("FFFFFFFFFFFFFFFF", 16).subtract(sum).add(BigInteger.ONE).toByteArray();
    }

Edit2:太糟糕了,这个问题被削弱了。它有很多有用的评论。

2 个答案:

答案 0 :(得分:1)

由于Java不会在算术溢出时抛出错误,因此您应该能够执行以下操作:

long sum = 0;
for (byte b : data)
    sum += (long) b;

return sum;

基于您希望与C#中的结果完全相同(二进制而不是值)的假设,简化了返回。 ulong.MaxValue是64位的1,在签名长度中为-1,取消“+1”。

编辑:我在这里撒谎。结果应该是逻辑上的-sum,由于默认的两个恭维实现,不能轻易完成。您应该考虑使用BigInteger解决方案。

Edit2:由于有符号减法的行为不均匀,因此无法简单地模拟无符号运算ulong.MaxValue - sum。我建议你做的是:

long sum = 0;
for (byte b : data)
    sum += ((long) b) & 0xFFL; // To prevent sign-expansion. Sorry, I missed this the first time as well.

return (new BigInteger("FFFFFFFFFFFFFFFF", 16)).subtract((new BigInteger(Long.toHexString(sum), 16))).add(BigInteger.ONE);

这看起来很难看,但我尽可能地使用本机算法。

您可以使用BitInteger的“toByteArray()”方法获取原始二进制文件以进行比较。不要使用longValue(),因为它会破坏第一位。

答案 1 :(得分:1)

ulong在Java中没有等价物。但是,您可以使用BigInteger处理它。

private static BigInteger Checksum(short[] data)
{
    BigInteger sum = BigInteger.ZERO;  
    for (short s : data)  
        sum = sum.add(BigInteger.valueOf((long)s)); 

    return new BigInteger("18446744073709551615", 10).subtract(sum).add(BigInteger.ONE); 
}

此外,由于字节是用Java签名的,因此您必须最多short才能获得0-255。

编辑:如果您的签名需要使用byte[]而不是short[]进行匹配,则billc.cn会有答案。