【问题标题】:Filename contains an umlaut (ä, ö, ü) and, therefore, the filename seems to be different文件名包含变音符号(ä、ö、ü),因此文件名似乎不同
【发布时间】:2021-06-08 23:30:51
【问题描述】:

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

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

有什么想法吗?

【问题讨论】:

  • strlen("Österreich"); 返回 11。因此,变音符号算作一个字符,或者需要 2 个字节来表示带有变音符号的字符 O。使用mb_strlen
  • readdir()的目录加载时数据是否可能不同?
  • 我不知道,您需要显示可以复制 12 的 strlen 的代码。但是 mb_strlen 在处理多字节内容时应该可以工作。
  • 好吧,即使它是 11(如您的示例中所示)也会导致问题。 Österreich 显然有 10 个字符。为什么这里这么复杂?
  • mb_strlen 返回 10。

标签: php utf-8 ascii


【解决方案1】:

提示是Ö 理想情况下应该是一个两字节的 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)

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

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

编辑

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

【讨论】:

  • 谢谢!但它说"Class 'Normalizer' not found"。我目前正在寻找解决方案
  • 您可能需要安装/启用intl 扩展。
  • 我在 php.ini 中启用了,还是不行。
猜你喜欢
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 2020-11-10
  • 2013-06-25
  • 2012-06-28
  • 2012-08-14
  • 2020-07-07
  • 1970-01-01
相关资源
最近更新 更多