【问题标题】:PHP doesn't recognize filename with apostrophe in itPHP 无法识别带有撇号的文件名
【发布时间】:2015-06-29 17:27:35
【问题描述】:

目前我正在尝试使用 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?
  • 如果我正确理解您的问题,那么如果您正在寻找 13067-AP-03 A - Situation projetee.pdf(不带重音),您确实会找到该文件。如果是这种情况,您可能会尝试在搜索之前对输入字符串运行字符串替换或正则表达式?
  • 它在我的机器上正常工作。你的 PHP 脚本的编码是什么,你在 php.ini 中的 default_charset 设置的值是多少?
  • 检查 php 文件本身是否也是 UTF-8 编码的。如果不是,则 php 脚本中的文件名将与文件系统中的不同。
  • 在调用file_exists 之前,您是否尝试过相反的iconv?看起来文件系统函数需要 437 而您的源文件是 UTF-8。

标签: php file-exists apostrophe


【解决方案1】:

我认为这是Windows下的PHP的问题。我下载了一个 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 有太多奇怪的问题。例如,Windows PHP 中的整数大小是 32 位,即使您使用的是 64 位二进制文​​件。这个问题是由msvc编译器引起的,它曾经让我困惑了很长时间。一些极客设法通过 MinGW 编译 PHP,但使用起来太不稳定了。
  • 那么就没有办法了吗?
  • @Quartermain 很抱歉,据我所知,我无法为您提供解决方案。
  • 至少 PHP 现在可以识别该文件。我可以用它自己更改文件的名称。谢谢。
【解决方案2】:

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

BOM 是字节顺序标记,位于文件开头的两个字节,允许软件读取文件以确定它是否已保存为 little-endian 或 big-endian,但是 PHP 解释器无法解释这些字符并且所以你必须保存没有字节顺序标记的文件。

【讨论】:

    【解决方案3】:

    在你的 php 文件的开头试试这个:

    <?php
    header('Content-Type: text/html; charset=utf-8');
    ?>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 1970-01-01
      相关资源
      最近更新 更多