字符编码错误

Character wrongly encoded

我有文件名中包含字符

这些文件在 Linux (Apache/php) 下得到了很好的处理:

$files = scandir($path);
echo json_encode($files);

file1⌐
file2⌐
file3⌐
file4⌐

在Windows下,它们似乎被文件系统读取为Windows-1252,所以我不得不有条件地转换它们,以便json_encode 可以工作

$files = scandir($path);
foreach ($files as $i => $file) {
    $files[$i] = mb_convert_encoding($file, 'UTF-8', 'Windows-1252');
}
echo json_encode($files);

这是他们如何转换的

file1¬
file2¬
file3¬
file4¬

为什么 被转换为 ¬ 我怎样才能得到原始字符?

请尝试对文件名的关键字符 ⌐ 进行 unpack('C*', $char) 。然后您会注意到它已经是 0xAC(即 ¬)。

原因是,scandir() 使用 Windows 的 8 位 ANSI Api 进行替换,并为不存在的字符提供一些 "closest matching character" Windows-1252。如果您使用文本编辑器 notepad++,将其设置为 ANSI 并尝试将您的 ⌐ 复制并粘贴到其中,您可以观察到相同的行为。它会显示为 ¬(有趣的是,当我在我的系统上尝试它时,它在 c&p 缓冲区中也发生了变化)。

你能做什么?那么这里有一些选项:

  1. 在Windows上使用shell_exec('dir /b')(我测试了这个,你得到了原始字符)
  2. 假设 ¬ 对 Windows 上的文件名表示 ⌐ 并在 utf-8 转换后将其替换回去
  3. 更改您的软件系统,使字符 ⌐ 不再用于文件名
  4. 使用一些具有函数 stream_encoding 的实验性 php 构建并尝试下面的代码。 (注意:stream_encoding 未定义,即使在以下官方版本中加载了 mbstring:5.6.19 7.0.4)
$myContext = stream_context_create();
stream_encoding($myContext, 'UTF-8');
$files = scandir('./', SCANDIR_SORT_ASCENDING, $myContext);

虽然通常应避免使用 shell_exec,但我认为这是您目前的最佳选择。从长远来看,如果可以的话,你应该选择 3。我不会推荐 4.(我也没有测试过)而且我对你的场景了解不够,无法判断 2. 是否可行。