Java多语言字符串处理问题:substring截取乱码如何解决?
问题分析与解决方案
你遇到的乱码问题,核心原因有两个:一是Java的String.substring默认按**UTF-16代码单元(即char类型,16位)**截取,而非实际的Unicode字符;二是原字符串可能存在编码错误,导致内部字符数组损坏。以下是具体解决方法:
1. 先确保原字符串编码正确
如果字符串来自外部(文件、网络、输入流),必须用正确编码(推荐UTF-8)解析:
// 读取文件示例 String str = new String(Files.readAllBytes(Paths.get("file.txt")), StandardCharsets.UTF_8);
如果是代码里的硬编码字符串,要保证Java文件本身是UTF-8编码,且编译时指定编码参数:
javac -encoding UTF-8 YourClass.java
避免编译器用默认编码(如GBK)解析非英语字面量,导致字符串本身已乱码。
2. 按实际Unicode字符(代码点)截取子串
对于包含补充平面字符(如emoji、部分生僻字)的字符串,直接用substring按char索引截取可能切断代理对,产生�乱码。此时需按代码点处理:
方法一:转换为代码点数组后截取
public static String substringByCodePoint(String str, int start, int end) { int[] codePoints = str.codePoints().toArray(); if (start < 0 || end > codePoints.length || start > end) { throw new IllegalArgumentException("无效索引范围"); } return new String(codePoints, start, end - start); }
调用时,传入实际字符的起止数量(比如截取前2个字符"на"):
String str = "наше"; String result = substringByCodePoint(str, 0, 2); assertEquals("на", result); // 校验通过
方法二:计算代码点对应的char索引
如果坚持使用substring,可以先通过代码点计算正确的char索引:
String str = "наше"; int startCharIndex = 0; // 从startCharIndex位置往后数2个实际字符,得到对应的char结束索引 int endCharIndex = Character.offsetByCodePoints(str, startCharIndex, 2); String result = str.substring(startCharIndex, endCharIndex); assertEquals("на", result);
针对你的代码修改
你的原代码:
String str = str.substring(0, 2); String result = ""; result += str; return result;
如果原字符串编码正确,俄语字符每个占1个char,这段代码本应有效。若仍乱码,优先排查原字符串的编码来源。如果需要兼容所有Unicode字符,替换为上述按代码点截取的方法即可。
内容的提问来源于stack exchange,提问作者John_Cena
相关产品推荐
相关产品推荐

