2013-03-15 29 views
0

我需要將上傳的文件名與未知編碼轉換爲Windows-1252,同時保持UTF-8兼容性。PHP編碼轉換爲Windows-1252,同時保持UTF-8兼容性

當我將這些文件傳遞給一個控制器(我沒有任何影響力)時,這些文件必須是Windows-1252編碼。這個控制器然後再次生成一個有效的文件(名稱)的列表,通過MySQL存儲到數據庫中 - 因此我需要UTF-8兼容性。傳遞給控制器​​的文件名和寫入數據庫的文件名必須匹配。到現在爲止還挺好。

在一些極少數情況下,當轉換爲「Windows-1252」(如使用te字符「ï」)時,字符在UTF-8中轉換爲無效。然後,MySQL刪除這些無效字符 - 結果磁盤上的文件名和存儲到數據庫的文件名不再匹配。這種轉換,有時失敗,系統用簡單的重新編碼來實現的:

$sEncoding  = mb_detect_encoding($sOriginalFilename); 
$sTargetFilename = iconv($sEncoding, "Windows-1252//IGNORE", $sOriginalFilename); 

爲了防止由轉換產生無效字符,我然後再次可以刪除所有無效UTF-8從重新編碼串字符:

ini_set('mbstring.substitute_character', "none"); 
$sEncoding  = mb_detect_encoding($sOriginalFilename); 
$sTargetFilename = iconv($sEncoding, "Windows-1252//TRANSLIT", $sOriginalFilename); 
$sTargetFilename = mb_convert_encoding($sTargetFilename, 'UTF-8', 'Windows-1252'); 

但是,這將完全刪除/重新編碼字符串中留下的任何特殊字符。例如,我失去了所有「äöüÄÖÜ」等,這在德語中很常見。

如果你知道一個更清潔和更簡單的編碼方式到Windows-1252(不丟失有效的特殊字符),請讓我知道。

任何幫助非常感謝。先謝謝你!

回答

1

我認爲問題在於mb_detect_encoding()並不完全符合您的想法。它試圖檢測字符編碼,但是它只是從相當有限的預定義編碼列表中完成的。默認情況下,這些編碼是由mb_detect_order()返回的編碼。在我的電腦,他們是:

  • ASCII
  • UTF-8

所以,除非你採取編譯候選編碼列表,並與它餵食的功能照顧這個功能是完全無用的。

此外,基本上沒有可靠的方法來猜測任意輸入字符串的編碼,即使您將自己限制爲一小部分編碼。在你的情況下,Windows-1252是如此接近ISO-8859-1ISO-8859-15,您除了目視檢查關鍵字符(例如&curren)外沒有辦法區分它們;或€。

2

您不能同時擁有一個字符串爲Windows-1252和UTF-8。字符集對於前128個字符是相同的(它們包含例如基本的拉丁字母),但是當它超出該範圍時(比如變音變音),它是一個或另一個。它們在UTF-8中的代碼點不同於Windows-1252中的代碼點。

1

在文件系統中保留ASCII - 如果您需要在文件名中保留ASCII外的字符,則可以使用 方案來表示unicode字符,同時保留ASCII。

例如,百分比編碼:

äöüÄÖÜ.txt < - >%C3%A4%C3%B6%C3%BC%C3%84%C3%96%C3%9C.txt

當然,這會打擊文件名稱限制相當快,也不是很理想。

punycode怎麼樣?

äöüÄÖÜ.txt < - >xn--4caa7cb2ac.txt