【问题标题】:Special ä ö characters break UTF-8 encoding特殊 ä ö 字符打破 UTF-8 编码
【发布时间】:2019-07-22 10:21:39
【问题描述】:

我网站上的用户在文本字段中输入了特殊字符:ä ö

这些显然与我可以从键盘输入的 ä ö 字符不同,因为当我将它们粘贴到程序员的记事本中时,它们分成了两个:a¨ o¨

在我网站的服务器端,我有一个 PHP 脚本,它可以识别用户输入中的非法特殊字符,并在带有 preg_replace 的 html 错误消息中突出显示它们。

字符拆分也发生在那里,所以我得到一个正常的字母 a 和 o,带有一个奇怪的单独 xCC 字符,它破坏了 UTF-8 字符串编码,json_encode 函数因此失败。

处理这些字符的最佳方法是什么?我应该尝试替换特殊的 ä ö 字符并用常规字符替换它们,还是我可以以某种方式捕获损坏的 UTF-8 字符并删除或替换它们?

【问题讨论】:

  • 听起来您的脚本可能一直没有设置为 UTF8,请查看 a previous answer of mineUTF-8 all the way through
  • @Qirel 我认为这里的编码没有任何问题;复制和粘贴它们的行为表明它们是有效的组合变音符号,脚本只是没想到这些。
  • @deceze 我不相信that question 是一个合适的副本。两者都是关于规范化的,但是一个需要 ASCII,这个很乐意使用 UTF-8。

标签: php encoding utf-8


【解决方案1】:

并不是这些字符破坏了编码,只是Unicode真的很复杂

常用的重音字母在 Unicode 标准中有自己的码位,在这种情况下:

  • U+00E4 "带分音符号的拉丁小写字母 A"
  • U+00F6 "带分音符号的拉丁小写字母 O"

但是,为了避免对所有可能性进行编码,特别是当需要在同一个字母上放置多个变音符号(重音符号)时,Unicode 包含“组合变音符号”,例如:

  • U+0308 "结合分音符"

当放置在普通字母的代码点之后时,这些代码点在显示时为其添加变音符号

如您所见,这意味着有两种不同的方式来表示同一个字母。为了解决这个问题,Unicode 包含“规范化形式”defined in an annex to the Unicode standard

  • 规范化表格 D (NFD):规范分解
  • 规范化表格 C (NFC):规范分解,然后是规范组合
  • 标准化形式 KD (NFKD):兼容性分解
  • 规范化形式 KC (NFKC):兼容性分解,然后是规范组合

暂时忽略“兼容性”表单,我们有两种选择:

  • 分解,尽可能频繁地使用组合变音符号
  • 组合,尽可能频繁地使用特定代码点

因此,一种可能性是将您的输入转换为 NFC,这在 PHP 中可以通过 the Normalizer class in the intl extension 实现。

但是,并非所有组合都可以规范化为没有单独变音符号的形式,因此这并不能解决您的所有问题。您还需要查看您想要允许的确切字符,可能是matching Unicode character properties

您可能还想了解“字素集群”并使用the relevant PHP functions。 “字素簇”,或者只是“字素”,是大多数读者认为的“一个字符”——例如。带有所有变音符号的字母或完整的表意文字。

【讨论】:

  • Normalizer 类确实解决了字符问题。感谢您的回答,内容非常丰富。我将不得不进一步研究此事并调整我的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
  • 2012-05-20
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多