2009-07-07 89 views
3

我有一個文件包含運行linux的服務器上的Unicode字符。如果我SSH進入服務器並使用tab-completion導航到包含unicode字符的文件/文件夾,則訪問該文件/文件夾時沒有問題。當我嘗試通過PHP訪問文件時出現問題(我從stat訪問文件系統的功能)。如果我將PHP腳本生成的路徑輸出到瀏覽器並將其粘貼到終端中,該文件似乎也存在(即使查看終端的文件路徑完全相同)。PHP和不同的Unicode編碼的UTF8文件名

我設置PHP使用UTF8作爲其默認編碼通過php_ini以及設置mb_internal_encoding。我檢查了PHP文件路徑字符串編碼,它以UTF8的形式出現,就像它應該的那樣。我決定把012終端的標籤完成,並將其與PHP腳本創建的'普通'字符的hexdump比較,或者通過鍵盤手動輸入字符(選項+ e +在OS X上)。結果如下:

 
echo -n é | hexdump 
0000000 cc65 0081        
0000003 
echo -n é | hexdump 
0000000 a9c3         
0000002 

允許在終端中正確引用文件的字符是3字節。我不知道該從哪裏下手,我應該在PHP中使用哪種編碼?我是否應該通過iconvmb_convert_encoding將路徑轉換爲另一種編碼?

回答

4

感謝這兩個答案中給出的提示,我能夠四處探索並找到一些方法來規範給定角色的不同Unicode分解。在我遇到的情況下,我正在訪問由OS X Carbon應用程序創建的文件。它是一個相當流行的應用程序,因此它的文件名似乎遵循特定的Unicode分解。

在PHP 5.3中引入了一個new set of functions,它允許您將unicode字符串規範化爲特定分解。顯然有四個分解標準,你可以分解你的Unicode字符串。自從2.3版本以來,Python通過unicode.normalize擁有unicode規範化功能。關於python處理unicode字符串的This article有助於理解編碼/字符串處理更好一點。

這裏是一個正常化的Unicode文件路徑一個簡單的例子:

filePath = unicodedata.normalize('NFD', filePath) 

我發現NFD格式工作了我所有的目的,我不知道這是這是Unicode文件名的標準分解。

3

三字節序列實際上是e (0x65)後跟一個combining ´ (0xcc 0x81)的utf8表示,而0xc3 0xa9表示「直接」表示é
utf-8意識到整理應該知道可能的分解,但我不知道如何在mac上啓用它(並可能重新編譯php源代碼)。
我能提供的最好的是"Using UTF-8 with Gentoo"的描述。

1

首先:你應該儘量避免在文件名上加上語義。我無法真正瞭解PHP爲什麼會在您的場景中生成文件名,因此我無法建議您應該如何應用此規則。

é的不同(兩字節和三字節)表示法是UTF-8對Unicode字符的組成和分解變體的編碼。在Unicode中,這些是表示相同視覺特徵的不同方式。 Unicode具有「規範化」的概念,其中將同一個字符的所有表示轉換爲單個表示,有點像將兩個字符串壓縮爲小寫以執行無情的比較。對於文件名,Linux不會自動執行規範化或任何其他處理,因此可以使用預組合(如兩字節序列)或分解(如三字節序列)字符或兩者的任意組合來命名文件,這取決於誰命名了這個文件。如果你正在創建這些文件,你可以設置一個策略(例如,總是使用預先組合的字符)並編寫一些代碼來執行它。否則,在這裏你不能依賴任何特定的規則。