【问题标题】:adler32 checksum in objective c [closed]目标c中的adler32校验和[关闭]
【发布时间】:2014-03-02 07:30:45
【问题描述】:

我正在开发一个应用程序,该应用程序将数据与用户位置信息一起发送到服务器。服务器根据校验和计算接受此数据,这是用 java 编写的。
这是用Java编写的代码:

private static final String CHECKSUM_CONS = "1217278743473774374";
private static String createChecksum(double lat, double lon) {

    int latLon = (int) ((lat + lon) * 1E6);
    String checkSumStr = CHECKSUM_CONS + latLon;
    byte buffer[] = checkSumStr.getBytes();
    ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
    CheckedInputStream cis = new CheckedInputStream(bais, new Adler32());
    byte readBuffer[] = new byte[50];
    long value = 0;
    try {
        while (cis.read(readBuffer) >= 0) {
            value = cis.getChecksum().getValue();
        }
    } catch (Exception e) {
        LOGGER.log(Level.SEVERE, e.getMessage(), e);
    }
    return String.valueOf(value);
}

我尝试寻求帮助以了解如何编写与此等效的目标 c。上面的函数使用adler32,我对此一无所知。请帮忙。

感谢您的宝贵时间。

【问题讨论】:

标签: ios iphone objective-c adler32


【解决方案1】:

基于wikipedia中提到的adler32校验和的定义,

Objective C 实现是这样的:

   static NSNumber * adlerChecksumof(NSString *str)
{
    NSMutableData *data= [[NSMutableData alloc]init];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    for (int i = 0; i < ([str length] / 2); i++)
    {
        byte_chars[0] = [str characterAtIndex:i*2];
        byte_chars[1] = [str characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [data appendBytes:&whole_byte length:1];
    }

    int16_t a=1;
    int16_t b=0;
    Byte * dataBytes= (Byte *)[data bytes];
    for (int i=0; i<[data length]; i++)
    {
        a+= dataBytes[i];
        b+=a;
    }

    a%= 65521;
    b%= 65521;

    int32_t adlerChecksum= b*65536+a;
    return @(adlerChecksum);
}

这里str 将是您在问题中提到的字符串..

所以当你想计算某个字符串的校验和时,只需这样做:

NSNumber * calculatedChkSm= adlerChecksumof(@"1217278743473774374");

如果需要更多信息,请告诉我

【讨论】:

  • 如果不使用ARC,则必须在返回校验和之前释放NSData。
  • 感谢和抱歉我迟到的回复。我现在要试试,很快就会回复。
  • @Volker,我尝试使用您的代码,但它返回的值与返回的一个 java 函数不同。通过对您的代码进行一些修改,最后我设法获得了正确的值。下面我发布了更新的代码。谢谢!
【解决方案2】:

@achievelimitless 和 @user3275​​097 此处显示的答案不正确。

首先,不应使用有符号整数。负数的模运算符在不同语言中的定义不同,应尽可能避免使用。只需使用无符号整数即可。

其次,循环会很快溢出 16 位累加器,从而给出错误的答案。模运算可以延迟,但必须在溢出之前完成。您可以通过假设所有输入字节为 255 来计算可以安全执行的循环次数。

第三,由于第二点,你不应该使用 16 位类型。您应该至少使用 32 位类型以避免经常进行模运算。您仍然需要限制循环的数量,但数量会变得更大。对于 32 位无符号类型,最大循环数为 5552。所以基本代码如下:

#define MOD 65521
#define MAX 5552

unsigned long adler32(unsigned char *buf, size_t len)
{
    unsigned long a = 1, b = 0;
    size_t n;

    while (len) {
        n = len > MAX ? MAX : len;
        len -= n;
        do {
            a += *buf++;
            b += a;
        } while (--n);
        a %= MOD;
        b %= MOD;
    }
    return a | (b << 16);
}

正如@Sulthan 所说,您应该简单地使用 zlib 中提供的 adler32() 函数,该函数已经存在于 Mac OS X 和 iOS 上。

【讨论】:

  • 我给你 +1 是因为......好吧,是你。但是,没有理由实现该算法,因为 zlib 库可以在 iOS 上使用它的所有功能,包括adler32
猜你喜欢
  • 2013-08-29
  • 2017-03-09
  • 1970-01-01
  • 2020-07-02
  • 2010-11-21
  • 1970-01-01
  • 2012-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多