波斯语字符串序列化中String.contains匹配失败求助
解决波斯语字符串
contains()方法匹配失败的问题 我之前处理RTL(从右到左)语言字符串的时候,也碰到过一模一样的问题——明明视觉上字符串是包含关系,但contains()就是返回false,核心原因基本都是Unicode规范化不一致在搞鬼。
为什么会出现这个问题?
波斯语的部分字符存在两种Unicode表示形式:
- 一种是预组合字符:比如字符"ک"直接用单个码点U+06A9表示
- 另一种是基础字符+组合标记:用基础字符U+0643加上组合标记U+0650来表示,视觉上和预组合的"ک"完全一样,但底层编码是两个字符
contains()方法是严格匹配字符编码的,所以哪怕看起来一样,编码不同就匹配不上。
解决方案:统一Unicode规范化格式
Java自带的Normalizer类可以帮我们把字符串转换成统一的规范化形式,推荐用NFC(预组合形式),步骤如下:
- 先导入
Normalizer类:
import java.text.Normalizer;
- 在匹配前对两个字符串做规范化处理:
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { String s = charSequence.toString().trim(); // 对目标字符串和搜索字符串做Unicode规范化 String normalizedFirstName = Normalizer.normalize(structuresMain.get(i).getFirstName(), Normalizer.Form.NFC); String normalizedQuery = Normalizer.normalize(s, Normalizer.Form.NFC); if (normalizedFirstName.contains(normalizedQuery)) { // 执行你的业务逻辑 } }
如果还是不行?检查隐藏的控制字符
有时候波斯语字符串会混入双向控制字符(比如U+200E、U+200F),这些字符看不到,但会占用字符串长度,影响匹配。可以尝试移除这些控制字符:
// 移除所有不可见的控制字符 String cleanFirstName = normalizedFirstName.replaceAll("\\p{C}", ""); String cleanQuery = normalizedQuery.replaceAll("\\p{C}", ""); if (cleanFirstName.contains(cleanQuery)) { // 执行你的业务逻辑 }
先试试规范化的方法,绝大多数情况下这个就能解决问题了。
内容的提问来源于stack exchange,提问作者Atras
相关产品推荐
相关产品推荐

