PHP:如何创建Unicode文件名

8

我希望创建文件名包含Unicode字符的文件。 我不太清楚应该使用什么编码,或者是否可能。

我有这个文件,以latin1编码保存:

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

在UTF-8中,这将解码为'unicode_♫.txt'。它将其写入磁盘的Latin1版本(这是显而易见的?)。我需要它保存为UTF-8解码后的样子。我也尝试过用UTF-16编码,但也不起作用。
我正在使用PHP 5.2,并希望它能在NTFS、ext3和ext4上运行。
如何实现这一点?

我有一个愚蠢的问题...为什么?https://dev59.com/RnI-5IYBdhLWcg3wBjhR - sdolgy
1
我认为限制因素是您服务器的操作系统。 - Wesley van Opdorp
1
可能是一个重复的问题:如何在 PHP 中使用文件系统函数,使用 UTF-8 字符串?(https://dev59.com/rXI_5IYBdhLWcg3wF_F3) - user
我已经在同一个问题中发布了答案 https://dev59.com/rXI_5IYBdhLWcg3wF_F3#32372692 - Oleg
4个回答

11

目前在Windows上无法实现这个功能(可能PHP 5.4会支持这种情况)。在PHP中,你只能使用Windows设置的代码页来编写文件名。如果代码页不包含字符 ,那就不能使用它。更糟糕的是,如果你在Windows上有一个文件名带有这样的特殊字符,你将难以访问它。

在Linux上,至少在ext*上,情况就不同了。你可以使用任何文件名,操作系统不关心编码。所以,如果你始终使用UTF-8编码的文件名,就应该没问题。但是UTF-16被排除在外,因为文件名不能包含值为0的字节。


5

对于我来说,以下代码在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;

1
但这仅适用于具有土耳其字符的文件,假设您的操作系统配置了土耳其代码页。 - Bigue Nique

1
使用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

首先要确认您的php.ini文件中已启用com_dotnet扩展,然后使用以下命令启用包装器:

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

最后,使用你熟悉的函数(如mkdir、fopen、rename等),但在路径前加上win://

例如:

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

0

文件名没有编码概念,你必须通过其他方式找出文件名。对于你的情况,唯一要注意的重点是,在大多数文件系统中,文件名是以空字符结尾的*字节*字符串,但在NTFS中,它是以空字符结尾的16位字符串。因此,您不能使用标准的fopen类型函数来访问所有可能的NTFS文件名。

但是,如果您已经通过其他方式获得了现有文件的NTFS文件名,则可以使用Windows API函数GetShortPathName获取文件的短名称,您可以在fopen中使用它。我不知道PHP是否允许您访问Windows API函数,但也许有人已经为此编写了模块或插件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接