PHP 无法识别其中包含重音字符“é”的文件名

问题描述 投票:0回答: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
不会将
解释为正确的字符。

php file-exists apostrophe
4个回答
2
投票

我认为这是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(微软称为Unicode)来保存其文件名。但 PHP 不支持 UTF-16LE 编码的文件名。

总之,遗憾的是,如果您在 Windows 上工作,我无法找到解决问题的方法,而不是在命名文件时转义所有这些字符。而且我也不认为PHP团队将来会解决这个问题。


0
投票

我发现这个功能帮助我解决了类似的问题。

来源:- https://www.php.net/urldecode

谢谢你alejandro at devenet dot net

function to_utf8( $string ) {

// From http://w3.org/International/questions/qa-forms-utf-8.html

if ( preg_match('%^(?:

  [\x09\x0A\x0D\x20-\x7E]            # ASCII

| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte

| \xE0[\xA0-\xBF][\x80-\xBF]         # excluding overlongs

| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte

| \xED[\x80-\x9F][\x80-\xBF]         # excluding surrogates

| \xF0[\x90-\xBF][\x80-\xBF]{2}      # planes 1-3

| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15

| \xF4[\x80-\x8F][\x80-\xBF]{2}      # plane 16

)*$%xs', $string) ) {
    return $string;
} else {
    return iconv( 'CP1252', 'UTF-8', $string);
}
}

-1
投票

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

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


-2
投票

在 php 文件的开头尝试一下:

<?php
header('Content-Type: text/html; charset=utf-8');
?>
© www.soinside.com 2019 - 2024. All rights reserved.