0

这是我的 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]
   ];

结果:

######### 来源 ©

[数据说明] = (null)
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]];

结果是############### source © len 2 [data description] = "<"c2a9>
md5: a541ecda3d4c67f1151cad5075633423

当我在 Java 中运行相同的函数时,我得到

>>>>>>味精## \251 \251
md5 a252c2c85a9e7756d5ba5da9949d57ed

问题是在 objC 中获得与在 Java 中获得相同字节的最佳方法是什么?

4

2 回答 2

6

“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]];

结果是

 ######### 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,因此 Unicode 中的前 128 个代码点是 ASCII 可以编码的。别的,ASCII 不能编码。

我见过NSASCIIStringEncoding的行为与NSISOLatin1StringEncoding以前相同;听起来他们可能已将其更改为纯 ASCII 编码,如果是这样的话,那是一件好事。ASCII 中没有版权符号。你在这里看到的是正确的结果。


*这并不完全正确;字符以 UTF-16 公开,因此基本多语言平面之外的任何字符都以代理对公开,而不是像在真正理想的字符串对象中那样的整个字符。这是一个权衡。在 Swift 中,内置的 String 类型是一个完美的理想 Unicode 对象;字符是字符,在编码之前从不分割。但是在使用 NSString 时(无论是在 Swift 中还是在 Objective-C 中),就您而言,您应该将其视为理想的字符串。

于 2010-11-24T20:36:18.147 回答
1

感谢 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];

}

于 2010-11-27T20:45:12.873 回答