我需要将带有未知编码的上传文件名转换为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编码方式(不会丢失有效的特殊字符),请告诉我。
非常感谢任何帮助。提前谢谢!
答案 0 :(得分:3)
您不能同时将字符串设置为Windows-1252和UTF-8。前128个字符的字符集是相同的(它们包含例如基本的拉丁字母),但是当它超出该字符集时(如同变形金刚),它可以是一个或另一个。它们在UTF-8中的代码点与在Windows-1252中的代码点不同。
答案 1 :(得分:2)
我认为主要问题是mb_detect_encoding()并不完全符合您的想法。它试图检测字符编码,但它是从一个相当有限的预定义编码列表中完成的。默认情况下,这些编码是mb_detect_order()返回的编码。在我的电脑里,他们是:
所以这个函数完全没用,除非你负责编译候选编码列表并用它来提供函数。
此外,基本上没有可靠的方法来猜测任意输入字符串的编码,即使您将自己局限于一小部分编码。在您的情况下,Windows-1252
非常接近ISO-8859-1
和ISO-8859-15
,除了目视检查¤或€等关键字符外,您无法区分它们。
答案 2 :(得分:1)
在文件系统中保持ASCII - 如果你需要在文件名中维持ASCII之外的字符,那么就有了 您可以使用的方案来表示unicode字符,同时保持ASCII。
例如,百分比编码:
äöüÄÖÜ.txt
< - > %C3%A4%C3%B6%C3%BC%C3%84%C3%96%C3%9C.txt
当然,这会非常快速地达到文件名限制。
punycode怎么样?
äöüÄÖÜ.txt
< - > xn--4caa7cb2ac.txt