2010-11-24 30 views
0

这是我MD5问题的另一个破解。我知道问题出在ASCII字符©(0xa9,169)。要么是我将字符插入到字符串中,要么是字符串中较高的字节或较低字节的字符。ASCII到NSData

如果我

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中运行相同的函数I得到

“>>>>> MSG ## \ 251 \ 251个
MD5 a252c2c85a9e7756d5ba5da9949d57ed

的问题是,什么是我在Java中去获得objC相同的字节的最好方法?

+1

你并不需要发送的对象的`description`消息,然后传递到`%@`。 '%@`格式化程序会为您发送一个“描述”消息。 – 2010-11-24 20:33:43

+1

您可能会考虑阅读http://www.joelonsoftware.com/articles/Unicode.html以获取有关字符和字节之间区别的一些基础知识。 – 2010-11-25 08:35:55

回答

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

}

6

“ASCII到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:

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

使用相同的编码。

没有“扩展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中)时,就您而言,您应该将其视为理想的字符串。

+0

+1优秀的答案! – walkytalky 2010-11-24 21:27:12