ASCII в NSData

Это еще одна трещина в моей проблеме с MD5. Я знаю, что проблема связана с символом ASCII © (0xa9, 169). Либо это способ, которым я вставляю символ в строку, либо проблема с более высоким и более низким байтом.

If I

 NSString *source = [NSString stringWithFormat:@"%c", 0xa9];

    NSData *data = [source dataUsingEncoding:NSASCIIStringEncoding];

    NSLog(@"\n\n ############### source %@ \ndata desc %@", source, [data description]);

CC_MD5([data bytes], [data length], result);

     return [NSString stringWithFormat:
   @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
   result[0], result[1], result[2], result[3], 
   result[4], result[5], result[6], result[7],
   result[8], result[9], result[10], result[11],
   result[12], result[13], result[14], result[15]
   ];

Результат:

######### source ©

[описание данных] = (null)
md5: d41d8cd98f00b204e9800998ecf8427e

значения: int 169 char ©

Когда я меняю кодировку на

NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source length]];

Результат

######### source ©

[описание данных] = "‹ "c2>
md5: 6465dad1d31752be3f3283e8f70feef7

Когда я меняю кодировку на

NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];

Результат: ############## источник © len 2 [описание данных] = "‹ "c2a9>
md5: a541ecda3d4c67f1151cad5075633423

Когда я запускаю ту же функцию на Java, я получаю

">>>>> msg ## \ 251 \ 251
md5 a252c2c85a9e7756d5ba5da9949d57ed

Вопрос в том, как лучше всего получить в objC тот же байт, что и в Java?


person Jim Geldermann    schedule 24.11.2010    source источник
comment
Вам не нужно отправлять объекту сообщение description, а затем передавать его %@. Модуль форматирования %@ отправляет объекту description сообщение.   -  person Peter Hosey    schedule 24.11.2010
comment
Вы можете прочитать joelonsoftware.com/articles/Unicode.html, чтобы получить некоторые основы разница между символами и байтами.   -  person Jon Hess    schedule 25.11.2010


Ответы (2)


«ASCII в NSData» не имеет смысла, потому что ASCII - это кодировка; если у вас есть закодированные символы, значит, у вас есть данные.

Кодирование - это преобразование идеальных символов Юникода (кодовых точек) в однобайтовые единицы (кодовые единицы), возможно, в таких последовательностях, как суррогатные пары UTF-16.

NSString - это более или менее идеальный объект Unicode. Он содержит символы строки в Юникоде независимо от кодировки *.

ASCII - это кодировка. UTF-8 также является кодировкой. Когда вы запрашиваете строку для ее UTF8String, вы просите ее кодировать свои символы как UTF-8.

NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source length]];

Результат

 ######### source ©
 [data description] = "<"c2>

Это потому, что вы пропустили неправильную длину. Длина строки (в символах) не совпадает с количеством единиц кода (в данном случае байтов) в некоторой кодировке.

Правильная длина - strlen([source UTF8String]), но вам проще и быстрее во время выполнения использовать dataUsingEncoding:, чтобы запросить строку для создания для вас объекта NSData.

Когда я меняю кодировку на

NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];

Вы не меняли кодировку. Вы все еще кодируете его как UTF-8.

Используйте dataUsingEncoding:.

Вопрос в том, как лучше всего получить в objC тот же байт, что и в Java?

Используйте ту же кодировку.

Не существует такого понятия, как «расширенный ASCII». Существует несколько различных кодировок, основанных на ASCII (или, по крайней мере, совместимых с ним), включая ISO 8859-1, ISO 8859-9, MacRoman, кодовую страницу Windows 1252 и UTF-8. Вам нужно решить, какой из них вы имеете в виду, и сказать строке, чтобы она кодировала свои символы.

Еще лучше, продолжайте использовать UTF-8 - это почти всегда правильный выбор для текста, в основном состоящего из ASCII, - и вместо этого измените свой код Java.

NSData *data = [source dataUsingEncoding:NSASCIIStringEncoding];

Результат:

[data description] = (null)

Истинный ASCII может кодировать только 128 возможных символов. Unicode включает в себя весь ASCII без изменений, поэтому первые 128 кодовых точек в Unicode - это то, что может кодировать ASCII. Все остальное ASCII не может кодировать.

Я раньше видел, как NSASCIIStringEncoding ведет себя как эквивалент NSISOLatin1StringEncoding; похоже, что они могли изменить его на чистую кодировку ASCII, и если это так, то это хорошо. В ASCII нет символа авторского права. Здесь вы видите правильный результат.


* Это не совсем так; символы представлены как UTF-16, поэтому любые символы за пределами базовой многоязычной плоскости отображаются как суррогатные пары, а не целые символы, как в действительно идеальном строковом объекте. Это компромисс. В Swift встроенный тип String - идеальный объект Unicode; символы - это символы, которые никогда не делятся, пока не закодированы. Но при работе с NSString (будь то в Swift или Objective-C), насколько вам известно, вы должны рассматривать его как идеальную строку.

person Peter Hosey    schedule 24.11.2010
comment
Да, я постепенно осознаю испытания своей дилеммы. Проблема в том, что Java 0xa9 используется в хэше MD5, и я получаю тот же результат, что и сервер. Я портирую Java на objC 1st для iPhone, а затем на OSX. Моя цель - отправить CC_MD5 байт, который даст мне результат, равный результатам Java и сервера. На этом этапе я считаю, что моя общая проблема с хешированием будет решена. Этот вопрос - попытка решить проблему путем атаки на лишний элемент. - person Jim Geldermann; 25.11.2010
comment
Джим: Проблема в том, что вы притворяетесь 0xa9 символом, когда это байт. Решение состоит в том, чтобы выяснить, какой символ вы имеете в виду, когда говорите 0xa9 в коде Java, затем определите, какая кодировка преобразует этот символ в однобайтный 0xa9, а затем используйте этот символ и эту кодировку в вашем коде Какао. - person Peter Hosey; 25.11.2010

Благодаря объяснению GBegan в другом посте я смог собрать это воедино.

for(int c = 0; c < [s length]; c++){
    int number = [s characterAtIndex:c];
    unsigned char c[1];
    c[0] = (unsigned char)number;
    NSMutableData *oneByte = [NSMutableData dataWithBytes:&c length:1];

}

person Jim Geldermann    schedule 27.11.2010