Java文本统计需优先选对字符串处理方式:用codePoints()而非chars()统计真实字符数,用Unicode标点正则分词替代简单空格切分,Files.readString()比new String()更稳且自动处理BOM,String::lines()需手动检查末尾换行符。

Java 里做文本统计,核心不是“写个工具”,而是选对字符串处理方式——String 的不可变性、编码隐含风险、正则边界陷阱,会直接让字数/词频结果出错。
用 String::chars() 还是 String::codePoints() 统计字符数?
中文、emoji、生僻字(如 ?、?)在 UTF-16 中可能占两个 char(即一个代理对),只用 chars() 会把一个 emoji 算成 2 个字符。
-
chars()返回IntStream,按char值切分,对 BMP 外字符不安全 -
codePoints()才真正按 Unicode 字符(code point)计数,推荐用于“真实字符数”统计 - 示例:"
??"(程序员 emoji)调用codePoints().count()得 1,chars().count()得 4(含零宽连接符)
按词频统计时,为什么 split("\s+") 不够用?
空格分词在中英文混排、标点紧贴文字、全角空格(u3000)等场景下会漏词或切错,比如 "hello,world!" 会被切为 ["hello,world!"](没切开)。
- 优先用
Pattern.compile("[\p{P}\s]+").splitAsStream(str),\p{P}匹配所有 Unicode 标点 - 若需保留英文单词但剥离中文标点,可先用
replaceAll("[\p{P}&&[^']]", " ")替换标点为空格,再split("\s+") - 注意:中文分词不能靠正则解决,遇到 "
南京市长江大桥",简单切分无法识别“南京市”还是“南京市长”
文件读取时,Files.readString() 和 new String(bytes, charset) 哪个更稳?
二者都依赖正确编码;但 Files.readString()(Java 11+)默认用 UTF-8,而手动用 new String(bytes, charset) 容易传错 Charset 或忽略 BOM。
立即学习“Java免费学习笔记(深入)”;
- 读取带 BOM 的 UTF-8 文件时,
Files.readString()自动跳过 BOM;手写new String(…)会把 BOM 当作普通字符计入统计 - 若必须用旧版 Java,建议用
Files.newBufferedReader(path, StandardCharsets.UTF_8)+lines().collect(Collectors.joining(" ")) - 绝对不要用
FileReader——它硬编码平台默认编码,Windows 上读 UTF-8 文件必然乱码
最常被绕过的点:统计“行数”时,String::lines() 按
|
|
切分,但某些日志文件末尾缺换行符,会导致最后一行被忽略——得手动检查原始字符串是否以换行结尾。










