这是对我的 MD5 问题的另一个破解。我知道问题出在 ASCII 字符 © (0xa9, 169) 上。这要么是我将字符插入字符串的方式,要么是高字节与低字节问题。
如果我
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]
];
结果:
#########来源©[数据描述] = (空)
md5: d41d8cd98f00b204e9800998ecf8427e
值:int 169 char ©
当我将编码更改为
NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source length]];
结果是
#########来源©[数据描述] = "<"c2>
MD5:6465dad1d31752be3f3283e8f70feef7
当我将编码更改为
NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
结果是
############### 来源 © len 2
[数据描述] = "<"c2a9>
md5:a541ecda3d4c67f1151cad5075633423
当我在 Java 中运行相同的函数时,我得到
">>>>> 消息##\251\251
md5 a252c2c85a9e7756d5ba5da9949d57ed
问题是在 objC 中获得与在 Java 中获得的相同字节的最佳方法是什么?
最佳答案
“ASCII to NSData”没有任何意义,因为 ASCII 是一种编码;如果你有编码字符,那么你就有数据。
编码是将理想的 Unicode 字符(代码点)转换为一个或多个字节单元(代码单元),可能采用 UTF-16 代理项对等序列。
NSString 或多或少是一个理想的 Unicode 对象。它包含字符串的字符,采用 Unicode,与任何编码无关*。
ASCII 是一种编码。 UTF-8也是一种编码。当您向字符串询问其 UTF8String
时,您是在要求它将其字符编码为 UTF-8。
NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source length]];
The result is
######### source © [data description] = "<"c2>
那是因为你传递了错误的长度。字符串的长度(以字符为单位)与某些编码中的代码单元数(在本例中为字节)不同。
正确的长度是 strlen([source UTF8String])
,但使用 dataUsingEncoding:
要求字符串创建为您提供 NSData 对象。
When I change the encoding to
NSData *data = [NSData dataWithBytes:[source UTF8String] length:[source lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
您没有更改编码。您仍然将其编码为 UTF-8。
使用dataUsingEncoding:
。
The question is what is the best way to get the same byte in objC as I get in Java?
使用相同的编码。
不存在“扩展 ASCII”这样的东西。有多种基于(或至少兼容)ASCII 的不同编码,包括 ISO 8859-1、ISO 8859-9、MacRoman、Windows 代码页 1252 和 UTF-8。您需要决定您指的是哪一个,并告诉字符串用它对其字符进行编码。
更好的是,继续使用 UTF-8(对于大多数 ASCII 文本来说它几乎总是正确的选择)并更改您的 Java 代码。
NSData *data = [source dataUsingEncoding:NSASCIIStringEncoding];
Result:
[data description] = (null)
真正的 ASCII 只能编码 128 个可能的字符。 Unicode 包含所有未更改的 ASCII,因此 Unicode 中的前 128 个代码点是 ASCII 可以编码的内容。其他任何东西,ASCII 都无法编码。
我之前见过 NSASCIIStringEncoding
的行为与 NSISOLatin1StringEncoding
相同;听起来他们可能已经将其更改为纯 ASCII 编码,如果是这样的话,那是一件好事。 ASCII 中没有版权符号。您在这里看到的是正确的结果。
*这并不完全正确;字符被公开为 UTF-16,因此基本多语言平面之外的任何字符都被公开为代理对,而不是像在真正理想的字符串对象中那样的整个字符。这是一个权衡。在 Swift 中,内置的 String 类型是一个完美理想的 Unicode 对象;字符就是字符,在编码之前不会被分割。但是当使用 NSString 时(无论是在 Swift 还是 Objective-C),就你而言,你应该将它视为理想的字符串。
关于cocoa - ASCII 到 NSData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4269094/