【问题标题】:Calculate checksum return wrong value in android在android中计算校验和返回错误值
【发布时间】:2016-10-26 11:48:29
【问题描述】:

您好,我正在将 c# 应用程序转换为 android,并且正在从字节数组计算校验和,与 c# 中的相同。但它在字节数组下方返回错误值。请任何人帮忙。谢谢。

C#字节数组:

[41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 13 2, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132, 41, 132、41、132、41、132、41、132、41、132]

c#代码:

public static uint CalculateChecksum(byte[] buffer, int offset, int length)
        {
            uint cs = 0;
            for (int i = offset; i < offset + length & i < buffer.Length; i += 2)
            {
                ushort s = BitConverter.ToUInt16(buffer, i);
                cs += s;
            }

            return cs;
        }

值得到 4736620 将此值转换为字节数组给出 [108,70,72,0]

Android 字节数组

[41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41 , -1 24, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, -124, 41, - 124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、- 124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、- 124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、-124、41、- 124]

安卓代码:

public static long checkSum(byte[] buffer, int offset, int length) {
        long cs = 0;
        for (int i = offset; i < offset + length & i < buffer.length; i += 2) {

            ByteBuffer bb = ByteBuffer.allocate(2);
            bb.order(ByteOrder.LITTLE_ENDIAN);
            bb.put(buffer[i]);
            bb.put(buffer[i+1]);
            long shortVal = bb.getShort(0);

            cs += shortVal;
        }
        return cs;
    }

值得到 -4438420 将此值转换为字节数组

ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt((int) value).array();

给出 [108,70,-68,-1]

做错了什么?为什么它返回不同的值? 请帮我。谢谢。

【问题讨论】:

    标签: java c# android bitconverter


    【解决方案1】:

    字节数组的内容不同(例如,C# 中的第二个位置与 Android 中的不同)。所以在我看来,代码返回不同的校验和是可以的。

    编辑:数组的内容确实不同。一个由有符号字节组成,另一个由无符号字节组成。这是一个区别(即使位表示可能相同)并且与大端与小端无关。您面临的问题是因为在 Java 版本中,您再次使用签名短裤,而 C# 版本使用未签名短裤。在那里,符号使计算错误的项是 2^16 的倍数。事实上,如果您在 C# 中使用 signed int16,您也将获得与 Android 解决方案相同的结果。

    因此,简单的解决方案是从字节缓冲区请求一个整数,而不是一个短整数,因为后者是有符号的。或者,您可以添加 2^16 以防 short 为负数(ushort 永远不可能):

    public static long checkSum(byte[] buffer, int offset, int length) {
        long cs = 0;
        for (int i = offset; i < offset + length & i < buffer.length; i += 2) {
    
            ByteBuffer bb = ByteBuffer.allocate(2);
            bb.order(ByteOrder.LITTLE_ENDIAN);
            bb.put(buffer[i]);
            bb.put(buffer[i+1]);
            long shortVal = bb.getShort(0);
            if (shortVal < 0) { shortVal += (1 << 16); }
            cs += shortVal;
        }
        return cs;
    }
    

    【讨论】:

    • 该字节数组采用 BigEndian 格式,即 (-124+256=132)。所以这就是为什么要从 LittleEndian 格式的返回值中获取字节数组,而在 java 中,字节数组在 c# 中是有符号的(-127 到 127),它的无符号(0 到 256)
    • @Nas 值是否有符号的差异仍然是值的差异。
    • 你的意思是第二个位置应该是上午 132 点,对吧?
    • @Nas 在android解决方案的空白行中,检查是否shortVal
    • 哦,你是对的。这是我的逻辑错误。谢谢你。现在我得到了相同的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 2016-03-09
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多