PHP无法识别带有撇号的文件名

4

目前,我正在尝试使用PHP检查文件是否存在。我要检查的文件名中包含一个撇号,该文件名为: 13067-AP-03 A - Situation projetée.pdf。

我用来检查文件是否存在的代码如下:

$filename = 'C:/13067-AP-03 A - Situation projetée.pdf';

if (file_exists($filename)) 
{
    echo "The file exists";
} else 
{
    echo "The file does not exist";
}

我现在面临的问题是,每当我试图检查文件是否存在时,都会收到“文件不存在”的消息。如果我继续删除é,我会收到文件确实存在的消息。
看起来PHP无法识别文件名中的撇号。我尝试了以下解决方法:
urlencode($filename);
addslashes($filename);
utf8_encode($filename);

所有这些都没有起作用。我还尝试了以下方法:

setlocale(LC_ALL, "en_US.utf8");

值得注意的是,当我从PHP获取文件名时,我会得到以下内容: 13067-AP-03 A - Situation projet�e.pdf

为了正确显示文件名,我必须执行以下操作:

$filename = iconv( "CP437", 'UTF-8', $filename);

我想知道是否有人遇到过同样的问题,能帮助我解决这个问题。非常感谢任何帮助。

对于那些感兴趣的人,该脚本在Windows机器上运行。

奇怪的是,这个方法有效:我将Sublime Text 3中的所有源代码复制到记事本中。然后我用记事本保存源代码,覆盖PHP文件。

现在,当我检查文件是否存在时,它显示存在以下文件名:

13067-AP-03 A - Situation projet�e.pdf

我目前遇到的唯一问题是,我想使用file_get_contents下载文件。但是,file_get_contents无法将�解释为撇号。


有可能相关的信息:你的脚本在哪个服务器上失败了?它是Windows机器还是Linux? - Lars Ebert
它在我的机器上可以正常运行。你的 PHP 脚本采用的是什么编码,php.ini 中的 default_charset 设置值是多少? - Frederick Zhang
检查php文件本身是否也是UTF-8编码。如果不是,则php脚本中的文件名与文件系统中的文件名将不同。 - Marius
在调用 file_exists 之前,你尝试过使用反向的 iconv 吗?看起来文件系统函数期望的是 437 编码,而你的源文件是 UTF-8 编码。 - Jon
@LarsEbert,该脚本在Windows机器上运行。 - Quartermain
显示剩余5条评论
3个回答

1

我认为这是PHP在Windows下的问题。我下载了一个Windows二进制副本到我的日语Windows上,并成功地重现了你的问题。

根据 https://bugs.php.net/bug.php?id=47096

所以,如果您拥有一个文件的通用名称(以及其路径)作为Unicode字符串$u(例如UTF-8编码),并且想尝试在Windows下使用该名称保存它,则必须首先调用setlocale(LC_CTYPE,0)来检查当前区域设置,然后必须将$u转换为字节数组,以符合代码页;如果一个或多个代码点在当前代码页中没有对应项,则无法从PHP使用该名称保存文件。点。

我的代码页是CP932,您可以通过在cmd中运行chcp来查看您的代码页。

因此,代码应该是:

$filename='C:\Users\Frederick\Desktop\13067-AP-03 A - Situation projetée.pdf';
$filename=mb_convert_encoding($filename, 'CP932', 'UTF-8');
var_dump($filename);
var_dump(file_exists($filename));

但这不起作用!为什么?因为CP932中不包含字符é
根据https://msdn.microsoft.com/en-us/library/windows/desktop/dd317748%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

NTFS使用Unicode存储文件名。相比之下,旧的FAT12、FAT16和FAT32文件系统使用OEM字符集。

Windows本身使用UTF-16LE(由Microsoft称为Unicode)来保存其文件名。但是PHP不支持UTF-16LE编码的文件名。
总之,如果您在Windows上工作,除了转义所有这些字符以命名文件,我很遗憾找不到解决问题的方法。而且我也不认为PHP团队将来会解决这个问题。

顺便说一下,我建议在Linux下运行PHP而不是Windows。 Windows版本的PHP存在太多奇怪的问题。例如,即使您使用64位二进制文件,Windows PHP中整数的大小仍为32位。该问题是由msvc编译器引起的,曾经让我困扰了很长时间。一些极客们设法通过MinGW编译PHP,但它太不稳定了,无法使用。 - Frederick Zhang
那么这个问题没有任何解决办法吗? - Quartermain
@Quartermain,很抱歉我无法给你一个解决方案,就我所知。 - Frederick Zhang
至少PHP现在能够识别这个文件了。我可以利用它来自己更改文件名。谢谢。 - Quartermain

-1

请确保您的文本编辑器将文件保存为“UTF-8无BOM”

BOM是字节顺序标记,它是放置在文件开头的两个字节,允许读取文件的软件确定它是否以小端或大端方式保存。但是,PHP解释器无法解释这些字符,因此您必须在不带字节顺序标记的情况下保存文件。


-2
在你的 PHP 文件开头尝试添加以下代码:
<?php
header('Content-Type: text/html; charset=utf-8');
?>

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