Различная контрольная сумма adler32 на target-c и C#
Я разрабатываю приложение для target-c, которое отправляет файл и контрольную сумму Adler32 этого файла в веб-службу.
После отправки файла на веб-сервер отвечает, что контрольная сумма не пройдена.
Это код, который я использую для проверки суммы по target-c:
//Get Asset NSData
ALAssetRepresentation *rep = [[p objectForKey:@"assetPath"] defaultRepresentation];
Byte *buffer = (Byte*)malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
//I also need a path to the file so I have to save the NSData to a local file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:@"png"];
[data writeToFile:localFilePath atomically:YES];
NSString *path = localFilePath;
//Now call the Adler
NSLog(@"checksum_fast:%@", [NSString stringWithFormat:@"%u", adler32_fast([data bytes], [data length])]);
NSLog(@"checksum:%@", [NSString stringWithFormat:@"%u", adler32([data bytes], [data length])]);
//Adler Lib
#define MOD_ADLER 65521
#define BUFFER_SIZE 1000
uint32_t adler32_update(uint32_t ck, const unsigned char data) {
uint32_t a = ck & 0x0ffff, b = (ck >> 16) & 0x0ffff;
a = (a + data) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
return (b << 16) | a;
}
uint32_t adler32(const unsigned char *data, int data_len) {
uint64_t ck = 1;
for(int i=0; i<data_len; i++) {
ck = adler32_update(ck,data[i]);
}
return ck;
}
uint32_t adler32_fast(const unsigned char *data, int data_len) {
uint32_t a = 1, b = 0;
for(int i=0; i<data_len; i++) {
a = (a + data[i]) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
}
return (b << 16) | a;
}
И это код веб-службы C#:
//It use ICSharpCode.SharpZipLib.dll
byte[] buff = null;
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(path).Length;
buff = br.ReadBytes((int)numBytes);
Adler32 adler = new Adler32();
adler.Reset();
adler.Update(buff, 0, buff.Length);
fs.Close();
fs.Dispose();
br.Close();
buff = null;
return Convert.ToString(adler.Value, 16);
Кто-нибудь знает, почему я получаю разные результаты контрольной суммы?
Тестовый файл: http://we.tl/gjqSj43238
Adler32 C#: 701ea682 (1881056898)
Adler32 Obj-C: 70100C51 (1880099921)
Спасибо!
1 ответ
Самое главное, что вы написали Адлер неправильно. Ваша константа должна быть MOD_ADLER
не MOD_ALDER
,
Вы не предоставили весь свой код, поэтому я не знаю, для чего вы установили эту константу.
Ваш код не "быстрый", как следует из названия, так как вы выполняете операции по модулю каждый раз. Нет никакого смысла в наличии двух вложенных циклов, если вы не собираетесь откладывать операции по модулю.
1 & 0xFFFF
кажется глупым, так как это всегда 1
,
Ваша ошибка в том, что вы инициализируете b
в 1
, Следует инициализировать в 0
,
Ах, я вижу еще одну ошибку: вам нужно использовать unsigned char
не char
для ваших массивов данных.
Я рекомендую вам скопировать adler32()
реализация в zlib.