我正在使用fopen()根据用户的输入创建文件名的文件。在大多数情况下,输入将是西里尔文。我希望能够在我的计算机上看到文件名,但看起来他们没有使用正确的编码,而我的操作系统(Windows 10)显示的内容是这样的 - “ЙосиС.txt”。
Windows使用UTF-16,因此我尝试将存储名称的变量的编码转换为UTF-16,但在使用fopen,fwrite和fclose时出错。
这是代码:
<?php
if(isset($_POST["submit"])) {
$name = $_POST["name"];
$file = fopen("$name.txt", "a");
fwrite($file, $string);
fclose($file);
}?>
答案 0 :(得分:3)
Windows和NTFS确实使用UTF-16作为文件名,因此您可以在其名称中读取和写入带有Unicode字符的文件。
但是,您需要调用相应的函数以利用Unicode:_wfopen()
(C运行时)或CreateFileW()
(Windows API)。请参阅What encoding are filenames in NTFS stored as?。
PHP的fopen()
不会调用这些函数中的任何一个,它使用普通的旧ANSI fopen()
,因为显然PHP不是使用the _UNICODE
constant which will cause fopen()
to be converted to _wfopen()
and so on编译的(另请参阅How to open file in PHP that has unicode characters in its name?和glob() can't find file names with multibyte characters on Windows?)。
请参阅下面的几个可能的解决方案。
数据库解决方案:在表中写入Unicode名称,并使用表的主键作为文件名。
您还可以使用音译(如PHP: How to create unicode filenames中所述),它将替换具有相似字符的目标字符集中不可用的Unicode字符。见php.net/iconv:
$filename = iconv('UTF-8', 'ASCII//TRANSLIT', "Žluťoučký kůň\n");
// "Zlutoucky kun"
请注意,这可能会导致冲突,因为可以将多个不同的Unicode字符音译为相同的ANSI字符序列。
另一个建议,如How do I use filesystem functions in PHP, using UTF-8 strings?中所见,是urlencode
文件名(注意你不应该直接将用户输入传递给文件系统,这样你就允许用户覆盖系统文件):
$name = urlencode($_POST["name"]) . ".txt";
$file = fopen($name, "a");
如果您的最终目标是在不更改任何代码的情况下编写具有Unicode文件名的文件,则必须使用_UNICODE
常量和Microsoft编译器在Windows上自行编译PHP,并希望它能够正常工作。我想不是。
或者,您可以使用How to open file in PHP that has unicode characters in its name?和use the WFIO extension中的建议,并通过wfio://
协议引用文件。
file_get_contents("wfio://你好.xml");