如何使用带有UTF 16编码的PHP函数fopen()创建文件?

时间:2016-03-22 14:47:48

标签: php encoding

我正在使用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);
}?>

1 个答案:

答案 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");

使用Windows Unicode支持重新编译PHP

如果您的最终目标是在不更改任何代码的情况下编写具有Unicode文件名的文件,则必须使用_UNICODE常量和Microsoft编译器在Windows上自行编译PHP,并希望它能够正常工作。我想不是。

最可行:WFIO

或者,您可以使用How to open file in PHP that has unicode characters in its name?use the WFIO extension中的建议,并通过wfio://协议引用文件。

file_get_contents("wfio://你好.xml");