如果文件名是 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 的文件名使用 phppathinfo() 函数时,它不会返回正确的值,除非特殊字符前面有“普通”字符。

示例: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() 返回正确的文件名的主要内容,如果未能解决你的问题,请参考以下文章

如果文本字符串小于屏幕大小,则使 textview 选取框

Chart JS - 如果数据过多,则使图表可滚动

recyclerview 中的 Diffutil,如果添加了新项目,则使其自动滚动

Spring security:如果用户不满足特定条件,则使每个页面重定向

如果在实体中添加或删除列,则使缓存无效(2LD 缓存休眠)。 (雷迪森)

如果 UICollectionView 没有足够的单元格来填充一行,则使第一行不完整而不是最后一行