Проблема с кодированием с помощью preg_replace() и scandir()
-
20-09-2019 - |
Вопрос
В OS-X (PHP5.2.11) у меня есть файл:siësta.doc (и тысячи других с именами файлов в Юникоде), и я хочу преобразовать имена файлов в формат, доступный для использования в Интернете (a-zA-Z0-9.).Если я жестко закодирую указанное выше имя файла, я смогу выполнить правильное преобразование:
<?php
$file = 'siësta.doc';
echo preg_replace("/[^a-zA-Z0-9.]/u", '_', $file);
// Output: si_sta.doc
?>
Но если я прочитаю имена файлов с помощью scandir, у меня получатся странные преобразования:
<?php
$files = scandir(DIRNAME);
foreach ($files as $file) {
echo preg_replace("/[^a-zA-Z0-9.]/u", '_', $file);
// Output for the file above: sie_sta.doc
}
?>
Я попытался определить кодировку, установить кодировку, преобразовать ее с помощью функций iconv.Я также попробовал функции mb_.Но это было только хуже.Что я сделал не так?
Заранее спасибо
Решение
Интересно.После небольшой проверки я обнаружил, что OSX хранит имена файлов как "разложенный юникод" (см. http://developer.apple.com/mac/library/qa/qa2001/qa1173.html).То есть "'" представлено как "e" + символ диареи (0xcc88).
Другие советы
Вы пробовали utf8_encode?(Работает, по крайней мере, в Windows)
<?php
$files = scandir(DIRNAME);
foreach ($files as $file) {
echo preg_replace("/[^a-zA-Z0-9.]/u", '_', utf8_encode($file));
// Output for the file above: sie_sta.doc
}
?>
Проблема заключается в связи между Windows и php.Невозможно получить имена файлов в юникоде, поскольку они зависят от языка приложения Windows, отличного от юникода.
Лучшее решение - выполнить команду dir и получить информацию для обработки, но вы должны сделать это с помощью cmd и получить короткие имена Windows:
chcp 65001
dir /x c:\test\ > myinfo.txt
Он возвращается:
El volumen de la unidad C es Windows8_OS
El número de serie del volumen es: 14A3-025F
Directorio de C:\test
22/12/2015 22:11 <DIR> .
22/12/2015 22:11 <DIR> ..
22/12/2015 22:12 0 a.txt
22/12/2015 22:10 <DIR> English
22/12/2015 22:10 <DIR> ESPAOL~1 Español
22/12/2015 22:11 <DIR> 8311~1 ру́сский язы́к
22/12/2015 22:10 <DIR> _0B41~1 عربي ,عربى
22/12/2015 22:10 <DIR> 8F4C~1 北方話
1 archivos 0 bytes
7 dirs 839.672.786.944 bytes libres
Затем вы можете прочитать myinfo.txt чтобы получить связь между оригинальным именем и кратким именем Windows.
Некоторые функции PHP прекрасно работают с короткими именами, и вы можете создавать и массивировать их так, как если бы вам нужно было их отобразить:
$array['short_name']= $original_name;
Например: is_dir, is_file
работает нормально.Однако, scandir
или is_readable
терпит неудачу и с короткими именами.Решение для использования этих функций заключается в рекурсивном повторном запуске команды dir.
Чтобы получить информацию из текстового файла, вы можете использовать регулярное выражение или substr, отбросив первые пять строк и последние две.Например:
for($k=6;$k<(count($array)-2);$k++) ...