2010-11-24 50 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