Java 比较两个在字典上等价但在字节级别不相同的字符串

Java 比较两个在字典上等价但在字节级别不相同的字符串,java,string,utf-8,Java,String,Utf 8,我正在寻找一种方法来比较两个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, 1

我正在寻找一种方法来比较两个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?

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

在本例中,一个US语言环境和一个三级强度足以使字符串相等

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

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

最后,take可能想看看(Unicode的国际组件)项目,该项目提供了许多工具,用于以多种不同的方式处理Unicode字符串。

您需要研究两种:

第一个是NFC和NFD。你在问题中给出的例子是NFC和NFD区别的一个很好的例子。您的第一个字符串在NFC中,而您的第二个字符串在NFD中

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

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


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

还有两种其他的规范化形式:NFKC和NFKD。这些表格不是一般用途,只是用于词典比较。它们解释了一个事实,例如,在搜索或比较中,¼应被视为与1/4相同。但它们并不意味着¼和1/4是相同的,或者一个通常应转换为另一个


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

它们在这里的呈现方式不同。@dystroy这导致我们重新考虑“词典等价”语句:)@dystroy(强烈)首选的web规范化形式是NFC。显然,您的web浏览器采用简单的快捷方式,只支持NFC,不支持NFD。不管它值多少钱,我的也一样。显然,web浏览器并不费心实现NFD。然而,我可以将这两个示例复制并粘贴到一个不同的应用程序中,该应用程序支持NFC和NFD,并且它们的显示方式相同。java提供了一个名为的内置类,可以将字符串转换为给定的Unicode格式+1,以获得详细的答案,该答案清楚地解释了问题的根本原因。我已经测试了Normalizer类,它可以工作完美地谢谢