2013-03-15 84 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