2011-04-08 29 views
13

如何在Mathematica中讀取utf-8編碼的文本文件?在Mathematica中讀取UTF-8編碼的文本文件

這是我現在在做什麼:

text = Import["charData.txt", "Text", CharacterEncoding -> "UTF8"]; 

,但它告訴我,

$CharacterEncoding::utf8: "The byte sequence {240} could not be interpreted as a character in the UTF-8 character encoding" 

等。我不知道爲什麼。我相信該文件是有效的utf-8。

這裏是我試圖讀取文件:

http://dl.dropbox.com/u/38623/charData.txt

+0

第十行包含「:Ba」的字符在Mathematica,Safari和TextEdit/BBEdit中看起來不同。 (我不會解釋這一點,只是指出它。) – 2011-04-08 15:22:58

+2

看起來它不支持4字節的UTF-8序列。可能是一個錯誤。 – kennytm 2011-04-08 15:25:40

+0

@Brett,同上TextMate/Chrome – 2011-04-08 17:09:14

回答

9

短版: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中也是如此;)

+0

我很好奇,你在什麼平臺上使用什麼版本的Mathematica?對於Windows XP上的版本8,前端無法處理。當粘貼它時(我不能使用IME輸入它),我會得到一個兩個字符的序列。此外,根據文檔,「Unicode」設置將讀爲「原始2字節Unicode值」,這與這個(以及您的其他發現)大體上是一致的。 – Szabolcs 2011-04-09 17:36:14

+0

@Szabolcs我在Windows 7 64位上使用Mathematica 8.0.1寫了這篇文章。只需一秒鐘,我會嘗試MMa 7 ...(暫停)是的,它也適用於我。不過,我剛剛注意到,當我重新打開包含此響應的筆記本時,所討論的角色現在顯示爲「缺失角色」正方形。筆記本不再正常工作。有趣。這些錯誤還在繼續... – WReach 2011-04-09 17:43:03

+1

我們可以從中學到的是,Mathematica無法解釋需要2個單元(4個字節)以UTF-16進行編碼的字符,但它會保留這些4個字節的序列不變。因此,數據仍然可以導出到其他應用程序(甚至通過從前端複製字符串並將其粘貼到其他位置!) 但處理我們需要記住的是,這些字符將被視爲兩個字符序列,因此功能,如StringLength數據時返回不正確的結果。 – Szabolcs 2011-04-09 17:48:07