0

我需要将上传的具有未知编码的文件名转换为 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 的方法(不会丢失有效的特殊字符),请告诉我。

非常感谢任何帮助。先感谢您!

4

3 回答 3

3

您不能同时将字符串设为 Windows-1252 和 UTF-8。前 128 个字符的字符集是相同的(它们包含例如基本的拉丁字母),但是当它超出此范围时(如元音变音符号),它要么是一个,要么是另一个。它们在 UTF-8 中的代码点与在 Windows-1252 中的不同。

于 2013-03-15T10:31:24.257 回答
3

我认为主要问题是mb_detect_encoding()并没有完全按照你的想法做。它试图检测字符编码,但它是从相当有限的预定义编码列表中进行的。默认情况下,这些编码是mb_detect_order()返回的编码。在我的电脑中,它们是:

  • ASCII
  • UTF-8

所以这个函数是完全没用的,除非你负责编译一个候选编码列表并将它提供给函数。

此外,基本上没有可靠的方法来猜测任意输入字符串的编码,即使您将自己限制在编码的一小部分。在您的情况下,Windows-1252非常接近,ISO-8859-1除了ISO-8859-15目视检查 ¤ 或 € 等关键字符外,您无法区分它们。

于 2013-03-15T10:44:15.067 回答
1

在文件系统中保持 ASCII - 如果您需要在文件名中保留 ASCII 以外的字符,可以使用一些方案来表示 unicode 字符,同时保持 ASCII。

例如,百分比编码:

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

当然,这会很快达到文件名限制,并且不是非常理想。

punycode怎么样?

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

于 2013-03-15T11:19:21.030 回答