Неверно закодированный символ


У меня есть файлы, содержащие символ в их названии.

Эти файлы хорошо обрабатываются в Linux (Apache/php):

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

Файл1⌐
файл2⌐
файл3⌐
файл4⌐

В 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);

Вот как они преобразуются

Файл1
файл2
файл3
файл4

Почему преобразуется в ¬ и как я могу получить исходный символ?

Author: Pierre de LESPINAY, 2016-03-11

1 answers

Пожалуйста, попробуйте распаковать ('C*', $char) на критическом символе ⌐ ваших имен файлов. Затем вы заметите, что это уже 0xAC (что и есть).

Причина этого в том, что scandir() использует 8-разрядный Api ANSI Windows, который выполняет подстановку и предоставляет некоторый "наиболее подходящий символ" для символов, которых нет в Windows-1252. Вы можете наблюдать такое же поведение, если получите текстовый редактор notepad++, установите для него значение ANSI и попробуйте скопировать и вставить в него свой ⌐. Он будет отображаться как (и забавно, что он также изменился в буфере c&p, когда я попробовал его в своей системе).

Что вы можете сделать? Ну вот несколько вариантов:

  1. Используйте shell_exec ('dir/b') в Windows (я проверил это, вы получите исходный символ)
  2. Предположим, что это означает ⌐ для имен файлов в Windows, и просто замените его обратно после преобразования utf-8
  3. Измените свою программную систему, чтобы символ ⌐ больше не использовался в именах файлов
  4. Используйте некоторую экспериментальную сборку 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.

.
 1
Author: Freitags, 2016-03-12 11:19:22