如果文件名是 UTF-8,则使 PHP pathinfo() 返回正确的文件名
Posted
技术标签:
【中文标题】如果文件名是 UTF-8,则使 PHP pathinfo() 返回正确的文件名【英文标题】:Make PHP pathinfo() return the correct filename if the filename is UTF-8 【发布时间】:2011-05-25 23:58:14 【问题描述】:当对已知为 UTF-8 的文件名使用 php 的 pathinfo()
函数时,它不会返回正确的值,除非特殊字符前面有“普通”字符。
示例:pathinfo('aä.pdf')
returns:
Array
(
[dirname] => [the dir]
[basename] => aä.pdf
[extension] => pdf
[filename] => aä
)
这很好,花花公子,但是pathinfo('äa.pdf')
returns:
Array
(
[dirname] => [the dir]
[basename] => a.pdf
[extension] => pdf
[filename] => a
)
这不是我所期望的。更糟糕的是,pathinfo('ä.pdf')
returns:
Array
(
[dirname] => [the dir]
[basename] => .pdf
[extension] => pdf
[filename] =>
)
为什么要这样做?这适用于我测试过的所有重音字符。
【问题讨论】:
大多数核心 PHP 函数不处理 ISO-8859-1 (Latin-1) 以外的字符集。您唯一真正的选择是使用多字节字符集安全函数(mb_string
函数)自己重新实现该函数
你运行的是哪个版本的 PHP ?
@ajreal 它是 debian lenny 上的 PHP 5.2.6-1+lenny9
打印到屏幕或终端时,您使用的是支持 UTF-8 的终端吗?当打印到屏幕(浏览器?)时,编码是否设置为 UTF-8?
对两者都是 :) 实际上文档现在已更新以反映 pathinfo() 是区域设置感知的。我仍然不确定发生了什么或发生了什么,我发布的解决方法仍然有效(如预期的那样),但我强烈怀疑这是服务器的语言环境搞砸了。
【参考方案1】:
使用前的路径信息
setlocale(LC_ALL,'en_US.UTF-8');
pathinfo($OriginalName, PATHINFO_FILENAME);
pathinfo($OriginalName, PATHINFO_BASENAME);
【讨论】:
如果您添加一些解释和文档链接,答案会变得更有价值,因此原始发布者和其他用户实际上可以从中学习。 这个答案很有帮助,而且很简单。请添加更多解释以增强其对其他人的价值。 里面有解释:***.com/questions/45268499/…【参考方案2】:我在 PHP 5.3.3 - 5.3.18 中使用这些函数来处理 basename() 和 pathinfo() 中的 UTF-8 问题。
if (!function_exists("mb_basename")) 函数 mb_basename($path) $分隔符 = "qq"; $path = preg_replace("/[^ ]/u", $separator."\$0".$separator, $path); $base = basename($path); $base = str_replace($separator, "", $base); 返回 $base; if (!function_exists("mb_pathinfo")) 函数 mb_pathinfo($path, $opt = "") $分隔符 = "qq"; $path = preg_replace("/[^ ]/u", $separator."\$0".$separator, $path); if ($opt == "") $pathinfo = pathinfo($path); 否则 $pathinfo = pathinfo($path, $opt); if (is_array($pathinfo)) $路径信息2 = $路径信息; foreach($pathinfo2 as $key => $val) $pathinfo[$key] = str_replace($separator, "", $val); 否则 if (is_string($pathinfo)) $pathinfo = str_replace($separator, "", $pathinfo); 返回$路径信息;【讨论】:
【参考方案3】:此问题的临时解决方法似乎是确保重音字符前面有一个“正常”字符,如下所示:
function getFilename($path)
// if there's no '/', we're probably dealing with just a filename
// so just put an 'a' in front of it
if (strpos($path, '/') === false)
$path_parts = pathinfo('a'.$path);
else
$path= str_replace('/', '/a', $path);
$path_parts = pathinfo($path);
return substr($path_parts["filename"],1);
请注意,我们将所有出现的“/”替换为“/a”,但这没关系,因为我们从结果的偏移量 1 开始返回。有趣的是,pathinfo()
的 dirname
部分似乎确实有效,因此不需要解决方法。
【讨论】:
这仍然是 2016 年的错误,但setlocale(LC_ALL,'en_US.UTF-8');
有效。【参考方案4】:
请参考“pathinfo() cannot handle argument with special characters like german 'Umlaute'”。
【讨论】:
该错误与非 ascii 字符有关,而不是 UTF-8 字符。所以我不确定它是否 100% 适用(它可能是,所以不是 -1,但它也是一个非常古老的错误,所以我相当确定这不是根本原因)...... @ircmaxell 我的角色确实是(或至少应该是)UTF-8。即:我的语言环境是 UTF-8,而 .php 文件另存为 UTF-8。我想我会使用 pathinfo() 重写函数以使用我自己的逻辑,但它有点“meh”。【参考方案5】:处理 ansi 字符时,函数 pathinfo 正确。
基于此注释,我们会将输入转换(编码)为 ansi 字符,然后仍然使用函数 pathinfo 来保留它的全部内容。
最后,我们将输出值转换(解码)为原始格式。
演示如下。
function _pathinfo($path, $options = null)
$path = urlencode($path);
$parts = null === $options ? pathinfo($path) : pathinfo($path, $options);
foreach ($parts as $field => $value)
$parts[$field] = urldecode($value);
return $parts;
// calling
_pathinfo('すtest.jpg');
_pathinfo('すtest.jpg', PATHINFO_EXTENSION);
【讨论】:
【参考方案6】:private function _pathinfo($path, $options = null)
$result = pathinfo(' ' . $path, $options);
return substr($result, 1);
【讨论】:
【参考方案7】:正如doc 所示,
注意
pathinfo() 是区域设置感知的,因此它解析包含 多字节字符正确,匹配的语言环境必须使用 setlocale() 函数。
以及手册中的example
【讨论】:
以上是关于如果文件名是 UTF-8,则使 PHP pathinfo() 返回正确的文件名的主要内容,如果未能解决你的问题,请参考以下文章
recyclerview 中的 Diffutil,如果添加了新项目,则使其自动滚动
Spring security:如果用户不满足特定条件,则使每个页面重定向