繁体   English   中英

比较两个在字典级别上按词典相同但不相同的字符串

[英]Compare two strings that are lexicographically equivalent but not identical at the byte level

我正在寻找一种方法来比较两个字典级别的词典等效但不相同的Java字符串。

更准确地说,使用以下文件名“baaaé.png”,在字节级别它可以用两种不同的方式表示:

[ 98,97,97,97-61,-87,46,112,110,103 ] - >“é”用2个字节编码

[ 98,97,97,97,101,-52,-127,46,112,110,103 ] - >“é”用3个字节编码

    byte[] ch = {98, 97, 97, 97, -61, -87, 46, 112, 110, 103};
    byte[] ff = {98, 97, 97, 97, 101, -52, -127, 46, 112, 110, 103};

    String st = new String(ch,"UTF-8");
    String st2 = new String(ff,"UTF-8");
    System.out.println(st);
    System.out.println(st2);
    System.out.println(st.equals(st2));

将生成以下输出:

baaaé.png
baaaé.png
false

有没有办法进行比较,以便equals方法返回true?

您可以使用具有适用强度的Collat​​or类来规范化不同重音符号等内容。 这将允许您成功地比较字符串。

在这种情况下,US语言环境和TERTIARY强度足以使字符串相等

Collator usCollator = Collator.getInstance();
usCollator.setStrength(Collator.TERTIARY);
System.out.println(usCollator.equals(st, st2));

输出

true

您还可以使用Java的Normalizer类在不同形式的Unicode之间进行转换。 这将转换您的字符串,但它们最终会相同,允许您使用标准字符串工具进行比较

最后,我们可能想看一下ICU (Unicode的国际组件)项目,它提供了许多工具,可以用很多不同的方式处理Unicode字符串。

您需要查看两种Unicode规范化表单

首先是NFC与NFD。 您在问题中提供的示例是NFC和NFD之间不同的一个很好的例子。 你的第一个字符串是NFC,而你的第二个字符串是NFD。

在Unicode中,许多重音字符可以用两种不同的方式表示:作为基本字符后跟组合重音,或作为预组合的重音字符。 NFC在可用区域时使用预先组合的字符。 NFD总是使用分解形式。

通常我们不使用NFC和NFD的混合物。 大多数环境指定哪个是首选形式。 非常简单:MacOS X文件名使用NFD,其他几乎所有使用NFC。 但是如果给你的输入可能是“其他”规范化形式,你可以轻松转换它:过程很简单(使用Unicode字符数据库提供的信息)和无损(即你可以在NFC之间来回切换)和NFD,如果你希望不丢失信息)。

java提供了一个名为Normalizer的内置类,它可以将字符串转换为给定的Unicode形式。

还有2种其他标准化形式:NFKC和NFKD。 这些表格不适用于一般用途,但仅用于词典比较。 例如,在搜索或比较中,¼应被认为与1/4相同。 但它们并不意味着¼和1/4是相同的,或者一般应该转换成另一个。

从NFC到NFKC以及从NFD到NFKD的转换再次简单(你需要角色数据库),但这次它是有损的。 您需要保留原始的NFC / NFD文本,并仅将NFKC / NFKD用作搜索/排序键。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM