Unicode 规范化形式解释 (Java)

问题描述 投票:0回答:1

我使用

Normalizer.normalize(url, Normalizer.Form.NFD)
是为了避免在我的网址中出现类似
é
的字符,并且我不明白
Normalizer.Form
常量(NFC、NFD、NFKC 和 NFKD)的含义或何时使用每一个。

我查阅了文档,但这根本没有帮助。 enter image description here

有人对这个话题有任何想法吗?

提前致谢!

java string
1个回答
3
投票
  • D=分解
    e
    ´
  • C=组成
    é

K 代表连字,一个字母

(ffi) 或 3:f f i。

这在javadoc中提到:

带重音符号或其他装饰的字符可以编码为多种 Unicode 中的不同方式。例如,以字符 A-acute 为例。在 Unicode,这可以编码为单个字符(“组合” 形式):

  U+00C1    LATIN CAPITAL LETTER A WITH ACUTE

或作为两个单独的字符(“分解”形式):

  U+0041    LATIN CAPITAL LETTER A
  U+0301    COMBINING ACUTE ACCENT

但是,对于程序的用户来说,这两个序列应该被视为相同的 “用户级”字符“带有锐音符号的A”。当你在寻找的时候 或比较文本,您必须确保这两个序列是 视为同等。此外,您必须使用以下方式处理字符 不止一种口音。有时角色的组合顺序 重音很重要,而在其他情况下重音序列 不同的命令实际上是等效的。同样,字符串“ffi” 可以编码为三个单独的字母:

  U+0066    LATIN SMALL LETTER F
  U+0066    LATIN SMALL LETTER F
  U+0069    LATIN SMALL LETTER I

或作为单个字符

  U+FB03    LATIN SMALL LIGATURE FFI

所以在你的情况下你想要 NFKD,完全分解。

s = Normalizer.normalize(s, Normalizer.Form.NFD).replaceAll("\\p{M}", "");

后者

replaceAll
只是删除了组合变音符号,零宽度重音符号
´
。仍然存在有问题的拉丁字母,例如

  • ŀ
    波兰语小 L 带删除线
  • ı
    土耳其小写 I 不带点
  • İ
    土耳其首都 I 带点

但可能已经在进行非 ASCII 替换。

当然,现在人们可能在某种程度上拥有 Unicode URLs,即带有特殊字符的网站。 只要小心一些,这些角色就不会被损坏。

分解形式标准化的另一个用途是按字母顺序对国家/地区名称进行排序:

Österreich
(德语中的奥地利)位于
P
之前。


一些细节

K 代表“兼容性”,因此很重要。

一个字母可以有多个重音符号(零宽度组合变音符号)。

一个人可以拥有一个同时包含组合字母和分解字母的字符串。

实际上 NFC 的作用是:规范分解,然后是规范组合。因此,为了做出好的构图,最好首先分解,这会为您提供标准化器。

组合也有它的用处;例如,它保证规范(单一规范形式),并且对于

String.codePointAt
来说是紧凑的。

© www.soinside.com 2019 - 2024. All rights reserved.