Arrays.mismatch可构建轻量文本差异定位器,逐行比对并精准返回首差异字符位置;支持JDK9+、零依赖、仅报告行号列号及两行内容,适用于CI检查或教学演示。

直接用 Arrays.mismatch 比较两行文本,再结合文件逐行读取,就能快速构建一个轻量、无依赖的文本差异定位器——它不生成 patch,也不高亮渲染,只精准告诉你“哪一行、从哪个字符开始不同”。
核心思路:逐行比对 + 字符级定位
Arrays.mismatch 接收两个 char[],返回首个不相等元素的索引(若完全相同则返回 -1)。这比字符串 equals 或 regionMatches 更细粒度,且 JDK 9+ 原生支持,无需额外库。
- 将两文件按行读入
List<String>,确保行数一致(或先对齐) - 对每一对对应行调用
Arrays.mismatch(line1.toCharArray(), line2.toCharArray()) - 结果为 -1 表示该行完全相同;否则返回差异起始位置(0 起始)
处理行数不等的常见情况
真实场景中,增删行很常见。mismatch 本身不处理长度差异,需前置判断:
- 若某一行为空而另一行非空 → 差异位置为 0(首字符就不同)
- 若两行长度不同但前缀相同(如 "abc" vs "abcd")→
mismatch返回较短者的长度(即第一个越界位置) - 建议先做行数比较:若行数不同,可标记“文件长度不一致”,再对公共行范围调用 mismatch
封装成可复用的差异扫描器
写一个极简工具类,输入两个文件路径,输出差异列表(行号、列号、两行内容):
立即学习“Java免费学习笔记(深入)”;
public record Diff(int line, int column, String left, String right) {}
public static List<Diff> diffFiles(Path a, Path b) throws IOException {
List<String> linesA = Files.readAllLines(a);
List<String> linesB = Files.readAllLines(b);
int maxLines = Math.min(linesA.size(), linesB.size());
List<Diff> diffs = new ArrayList<>();
for (int i = 0; i < maxLines; i++) {
String la = linesA.get(i), lb = linesB.get(i);
int pos = Arrays.mismatch(la.toCharArray(), lb.toCharArray());
if (pos != -1) {
diffs.add(new Diff(i + 1, pos + 1, la, lb));
}
}
return diffs;
}
注意:行号从 1 开始,列号也从 1 开始(更符合编辑器习惯);若需报告缺失行,可在循环后追加逻辑。
提升实用性的小技巧
真正用起来,几个细节让结果更友好:
- 忽略行尾换行符差异:读取时用
Files.readAllLines自动去除 \r\n/\n,避免因换行符不同误报 - 跳过空白行对比(可选):在循环内加
if (la.trim().isEmpty() && lb.trim().isEmpty()) continue; - 限制输出长度:对超长行只截取差异点前后 20 字符,避免日志刷屏
- 区分大小写?默认区分;如需忽略,提前统一转小写再比对(但注意影响列号准确性)
不复杂但容易忽略:mismatch 是纯数组比对,不关心语义,所以它快、稳、零依赖——正适合嵌入脚本、CI 检查或教学演示中的“最小可行差异器”。


















