PHP: Как создать имена файлов в Юникоде

Я пытаюсь создать файлы с символами Unicode в именах файлов. Я не совсем понимаю, какую кодировку я должен использовать, или если это вообще возможно.

У меня есть этот файл, сохраненный в латинской кодировке:

$h = fopen("unicode_♫.txt", 'w'); fclose($h); 

В UTF-8 это будет декодироваться как «unicode_ ♫ .txt». Он записывает его в версии latin1 на диск (что очевидно?). Мне нужно, чтобы он был сохранен, как это было бы с расширением UTF-8. Я также пробовал кодировать его с помощью UTF-16, но это тоже не работает.

Я использую PHP 5.2 и хотел бы, чтобы это работало с NTFS, ext3 и ext4.

Как это может быть сделано?

В настоящее время это невозможно сделать в Windows (возможно, PHP 5.4 будет поддерживать этот сценарий). В PHP вы можете писать только имена файлов, используя установленную кодировку Windows. Если кодовая страница не содержит символа , вы не можете ее использовать. Хуже того, если у вас есть файл в Windows с таким символом в имени файла, у вас возникнут проблемы с его доступом.

В Linux, по крайней мере, с ext *, это совсем другая история. Вы можете использовать любые имена файлов, которые вам нужны, ОС не заботится о кодировке. Поэтому, если вы последовательно используете имена файлов в UTF-8, вы должны быть в порядке. UTF-16, однако, исключается, поскольку имена файлов не могут содержать байты со значением 0.

для меня код ниже хорошо работает на Win7 / ntfs, Apache 2.2.21.0 и PHP 5.3.8.0:

 <?php // this source file is utf-8 encoded $fileContent = "Content of my file which contains Turkish characters such as şığŞİĞ"; $dirName = 'Dirname with utf-8 chars such as şığŞİĞ'; $fileName = 'Filename with utf-8 chars such as şığŞİĞ'; // converting encodings of names from utf-8 to iso-8859-9 (Turkish) $encodedDirName = iconv("UTF-8", "ISO-8859-9//TRANSLIT", $dirName); $encodedFileName = iconv("UTF-8", "ISO-8859-9//TRANSLIT", $fileName); mkdir($encodedDirName); file_put_contents("$encodedDirName/$encodedFileName.txt", $fileContent); 

вы можете сделать то же самое для открытия файлов:

 <?php $fileName = "Filename with utf-8 chars such as şığ"; $fileContent = file_get_contents(iconv("UTF-8", "ISO-8859-9//TRANSLIT", "$fileName.txt")); print $fileContent; 

Используя расширение com_dotnet PHP, вы можете получить доступ к Windows Scripting.FileSystemObject , а затем сделать все, что хотите, с именами файлов / папок UTF-8.

Я упаковал это как оболочку потока PHP, поэтому он очень прост в использовании:

https://github.com/nicolas-grekas/Patchwork-UTF8/blob/lab-windows-fs/class/Patchwork/Utf8/WinFsStreamWrapper.php

Сначала убедитесь, что расширение com_dotnet включено в вашем php.ini затем включите оболочку с помощью:

 stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper'); 

Наконец, используйте функции, к которым вы привыкли (mkdir, fopen, rename и т. Д.), Но префикс вашего пути с помощью win://

Например:

 <?php $dir_name = "Depósito"; mkdir('win://' . $dir_name ); ?> 

Имена файлов не имеют понятия кодирования. Вы должны определить имя файла другими способами. Единственным важным моментом в вашей ситуации является то, что в большинстве файловых систем имя файла – это строка с байтом * с нулевым символом, но в NTFS это 16-разрядная строка с нулевым завершением. Следовательно, вы не можете использовать стандартные функции типа fopen для доступа ко всем возможным именам файлов NTFS.

Однако, если вы получили имя файла NTFS существующего файла другими способами, вы можете использовать функцию GetShortPathName в Windows API для получения краткого имени файла, которое вы можете использовать в fopen . Я не знаю, поддерживает ли PHP доступ к функциям Windows API, но, возможно, кто-то написал для этого модуль или плагин.