短版:Mathematica的UTF-8功能不適用於字符代碼與超過16位的工作。如果可能,請使用UTF-16編碼。但請注意,Mathematica對17位以上字符代碼的處理通常是錯誤的。長版本如下...
正如許多評論者所指出的,問題似乎與Mathematica對代碼大於16位的Unicode字符的支持有關。引用文本文件中的第一個這樣的字符是U+20B9B(),它出現在第10行上。
某些版本的Mathematica前端(如64位Windows 7上的8.0.1)可以處理有問題的字符直接輸入:
In[1]:= $c="";
但我們遇到麻煩,如果我們試圖從它的Unicode創建的字符:
In[2]:= 134043 // FromCharacterCode
During evaluation of In[2]:= FromCharacterCode::notunicode:
A character code, which should be a non-negative integer less
than 65536, is expected at position 1 in {134043}. >>
Out[2]= FromCharacterCode[134043]
我們不禁要問,什麼是數學認爲的代碼是這個字符ACTER?
In[3]:= $c // ToCharacterCode
BaseForm[%, 16]
BaseForm[%, 2]
Out[3]= {55362,57243}
Out[4]//BaseForm= {d842, df9b}
Out[5]//BaseForm= {1101100001000010, 1101111110011011}
不像人們所期望的那樣使用一個Unicode值,我們得到了兩個恰好匹配該字符的UTF-16表示的代碼。 Mathematica可以進行逆變換,以及:
In[6]:= {55362,57243} // FromCharacterCode
Out[6]=
那麼,什麼是Mathematica的這個字符的UTF-8編碼的概念?
In[7]:= ExportString[$c, "Text", CharacterEncoding -> "UTF8"] // ToCharacterCode
BaseForm[%, 16]
BaseForm[%, 2]
Out[7]= {237,161,130,237,190,155}
Out[8]//BaseForm= {ed, a1, 82, ed, be, 9b}
Out[9]//BaseForm= {11101101, 10100001, 10000010, 11101101, 10111110, 10011011}
細心的讀者會發現,這是字符的UTF-16編碼的UTF-8 encoding。 Mathematica可以解碼這個,嗯,有趣的編碼?
In[10]:= ImportString[
ExportString[{237,161,130,237,190,155}, "Byte"]
, "Text"
, CharacterEncoding -> "UTF8"
]
Out[10]=
是的,可以!但是......那麼是什麼?
這個怎麼樣性格的真正 UTF-8的表達:
In[11]:= ImportString[
ExportString[{240, 160, 174, 155}, "Byte"]
, "Text"
, CharacterEncoding -> "UTF8"
]
Out[11]= $CharacterEncoding::utf8: The byte sequence {240} could not be
interpreted as a character in the UTF-8 character encoding. >>
$CharacterEncoding::utf8: The byte sequence {160} could not be
interpreted as a character in the UTF-8 character encoding. >>
$CharacterEncoding::utf8: The byte sequence {174} could not be
interpreted as a character in the UTF-8 character encoding. >>
General::stop: Further output of $CharacterEncoding::utf8 will be suppressed
during this calculation. >>
ð ®
...但是我們看到在原來的問題報告的故障。
UTF-16如何?UTF-16不在有效的字符編碼列表中,但是"Unicode"
是。既然我們已經看到,數學似乎使用UTF-16作爲其原生格式,讓我們給它一個旋轉(使用大端UTF-16字節順序標記):
In[12]:= ImportString[
ExportString[
FromDigits[#, 16]& /@ {"fe", "ff", "d8", "42", "df", "9b"}
, "Byte"
]
, "Text"
, CharacterEncoding -> "Unicode"
]
Out[12]=
它的工作原理。作爲一個更完整的實驗,我將從問題轉換爲UTF-16併成功導入它。
Mathematica文檔在這個問題上基本沒有提及。值得注意的是,在Mathematica中提到Unicode似乎伴隨着字符碼包含16位的假設。例如,參見Raw Character Encodings中對Unicode的引用。
由此得出的結論是,Mathematica對UTF-8轉碼的支持缺少長度超過16位的代碼。 UTF-16是Mathematica的明顯內部格式,似乎可以正常工作。所以這是一個解決方法,如果你能夠重新編碼你的文件和你可以接受的結果是字符串實際上是UTF-16格式,而不是真正的Unicode字符串。
後記
一會兒寫這個響應後,我試圖重新打開Mathematica筆記包含它。筆記本中出現的每一個有問題的字符都被擦掉了,換成亂碼。我認爲還有更多的Unicode錯誤,即使在Mathematica 8.0.1中也是如此;)
第十行包含「:Ba」的字符在Mathematica,Safari和TextEdit/BBEdit中看起來不同。 (我不會解釋這一點,只是指出它。) – 2011-04-08 15:22:58
看起來它不支持4字節的UTF-8序列。可能是一個錯誤。 – kennytm 2011-04-08 15:25:40
@Brett,同上TextMate/Chrome – 2011-04-08 17:09:14