2013-06-24 37 views
2

我有一個包含混合二進制和UTF-8編碼數據的文件。當二進制數據解碼爲UTF-8時會發生什麼?

它看起來像

----------------- 
| Binary data | 
| (unknown len) | 
+---------------+ 
| Delimiter | 
+---------------+ 
| UTF-8 string | <--- only relevant part of file 
+---------------+ 
| Delimiter | 
+---------------+ 
| Binary data | 
----------------- 

我想提取文本,並且不關心的二進制內容。我正在將文件讀入字符串,將所有內容解碼爲UTF-8,然後使用NSScanner查找分隔符。

我擔心的是,根據二進制數據的內容,將其解碼爲UTF-8可能會導致某種偏移問題,導致無法找到分隔符。 (在分隔符使得下一個序列解析爲多個字節之前說出數據,並且它會丟失。)

此代碼是否會遇到某些內容的問題?

NSString *fileContents = [NSString stringWithContentsOfFile:path 
                encoding:NSUTF8StringEncoding 
                 error:NULL]; 
NSScanner *scanner = [NSScanner scannerWithString:fileContents] 
[scanner [email protected]"<DELIMITER>" intoString:nil]; 
// TODO: remove delimiter 
NSString *desiredString; 
[scanner scanUpToString:@"<DELIMITER2>" intoString:&desiredString]; 

回答

2

你是對的,你應該擔心。原則上,根據定界符的選擇以及UTF-8解碼器的實現,從定界符開始的某些字節可能會被解碼爲由前導二進制數據形成的某個unicode字符的最後一個字節。

在這種情況下,您可能會很幸運,因爲您的<DELIMITER>的字符都適合在7位ASCII集中,而多字節UTF-8字符的所有字節將全部設置第8(高)位的字節(http://en.wikipedia.org/wiki/UTF-8#Description)。 UTF-8解碼器不應該像'<'那樣抓取'<',但我不會指望它。

將文件內容作爲二進制字節數組/緩衝區讀取,並且有一個分隔符(並確保它不會因其他原因而突然隨機出現在二進制數據的中間,這當然是一個好主意。 。任何這樣的事件都應該被轉義或二進制數據以某種方式編碼以便它不能包含分隔符),在分隔符之間提取utf-8編碼的字符串,然後進行utf-8解碼。

3

UTF-8多字節序列由只在0x80的– 0xFF的範圍的字節,因此,假設你的定界符是字面上如圖所示(<DELIMITER><DELIMITER2>),它們完全由字符不能是一個多字節的一部分序列。 (任何純ASCII字符串都具有此屬性。)

但是,UTF-8序列也是長度標記的。舉例來說,如果你有三字節序列

E2 80 3C 

的E2表示它是一個3字節序列的第一個字節,但隨後的3C不能是序列的一部分。一個UTF-8解碼器應該要麼拋出一個錯誤,要麼產生雙碼點序列U + FFFD U + 003C,但我不會感到驚訝的解碼器,而是吃3C而只產生一個替換字符。

因此,你建議的是不安全的,你應該改爲(如oh71zb建議)以二進制讀取文件,掃描分隔符,提取它們之間的內容,然後纔將這些字節解釋爲UTF-8 。

相關問題