在Unicode中,某些字符可以用多種方式表示。例如,在單詞BAI中間字符可以以兩種方式表示:
- 單個碼點U + 00E3(WITH TILDE拉丁小寫字母A)
- 兩個編碼點U + 0061(拉丁小字母A)和U + 0303(組合TILDE)
對於顯示,兩者應該看起來相同。
對於字符串比較,這提出了一個問題。解決方法是根據Unicode Standard Annex #15 — Unicode Normalization Forms首先對字符串進行標準化。
通過Normalizer class(Android請參閱Normalizer)在Java(包括Android)中支持標準化。
下面的代碼示出了結果:
String s1 = "b\u00e3i";
String s2 = "ba\u0303i";
System.out.println(String.format("Before normalization: %s == %s => %b", s1, s2, s1.equals(s2)));
String n1 = Normalizer.normalize(s1, Form.NFD);
String n2 = Normalizer.normalize(s2, Form.NFD);
System.out.println(String.format("After normalization: %s == %s => %b", n1, n2, n1.equals(n2)));
它輸出:
Before normalization: bãi == bãi => false
After normalization: bãi == bãi => true
順便說一句:表單Form.NFD
分解字符串,即它產生具有兩個編碼點的時間越長表示。 Form.NFC
會創建較短的表單。
此問題不是http://stackoverflow.com/questions/8854106/java-string-encoding-utf-8的副本。它以「ã」的表示爲中心,可能在第一種情況下作爲單個Unicode代碼點(U + 00E3)給出,在第二種情況下作爲兩個單獨的代碼點(U + 0061和U + 0303)給出。 – Codo
在比較它們之前,先對字符串進行標準化。這應該消除與組合字符相關的差異。請參閱[Normalizer](https://developer.android.com/reference/java/text/Normalizer.html)。 – Codo
@IntelliJAmiya:請重新提問。這不是重複的,因爲您仔細閱讀時會看到它。 – Codo