首页 > 解决方案 > 文件名包含变音符号(ä、ö、ü),因此文件名似乎不同

问题描述

当我从数据库加载“Österreich”时,它与我的文件名“Österreich”不匹配。那就是问题所在。

我有一个名为“Österreich.php”的文件,我想从相应的目录中读取它。当我strlen()在“Österreich”(不是“.php”)上使用时,它返回 12,但是,它应该是 10。这会导致问题,因为我想用它从数据库中加载数据,无论出于何种原因,它似乎是一个“不同”的词。

有任何想法吗?

标签: phputf-8ascii

解决方案


提示是Ö理想情况下应该是一个两字节的 UTF8 序列,字符串的字节长度是 11,而不是 12。

我能想到的唯一方法是Österreich占用 12 个字节,如果它是一个非理想但仍然有效的常规形式O加上一个单独的变音符号组合标记。例如:O\u{0308}sterreich

function utf8_denormalize($string) {
    return implode('',
        array_map(
            function($c){
                if(strlen($c) > 1){
                    return Normalizer::getRawDecomposition($c);
                }
                return $c;
            },
            preg_split('//u', $string)
        )
    );
}

$str1 = "Österreich";
$str2 = "O\u{0308}sterreich";
$str3 = Normalizer::normalize($str2);
$str4 = utf8_denormalize($str1);

var_dump(
    $str1,
    $str2,
    $str3,
    $str4,
    $str1 === $str3,
    $str2 === $str4
);

输出:

string(11) "Österreich"
string(12) "Österreich"
string(11) "Österreich"
string(12) "Österreich"
bool(true)
bool(true)

我会说应该检查和/或规范化此问题双方的数据,但您也应该小心,因为您的数据库和/或由规范化和非规范化形式组成的文件系统中可能有“重复”文件名各种字符串。

https://www.php.net/manual/en/normalizer.normalize.php

编辑

Mac HFS 是愚蠢的,并且需要文件名的非规范化形式。我拼凑了一个反规范化器 [YMMV] 但老实说,除非您的生产环境是 Mac 机器,否则您应该针对与您的生产环境尽可能匹配的 VM 测试您的代码。文件系统的特殊性只是会影响工作的众多边缘案例之一。


推荐阅读