- 一、准备
- 二、后端实现
- 三、前端实现
1.Java使用的库 java-diff-utils
2.前端使用的库 diff2html
二、后端实现用java-diff-utils 封装了一个工具类 DiffHandleUtils.java
import com.github.difflib.UnifiedDiffUtils;
import com.github.difflib.patch.Patch;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class DiffHandleUtils {
public static List diffString(List original, List revised) {
return diffString(original, revised, null, null);
}
public static List diffString(List original, List revised, String originalFileName, String revisedFileName) {
originalFileName = originalFileName == null ? "原始文件" : originalFileName;
revisedFileName = revisedFileName == null ? "对比文件" : revisedFileName;
//两文件的不同点
Patch patch = com.github.difflib.DiffUtils.diff(original, revised);
//生成统一的差异格式
List unifiedDiff = UnifiedDiffUtils.generateUnifiedDiff(originalFileName, revisedFileName, original, patch, 0);
if (unifiedDiff.size() == 0) {
//如果两文件没差异则插入如下
unifiedDiff.add("--- " + originalFileName);
unifiedDiff.add("+++ " + revisedFileName);
unifiedDiff.add("@@ -0,0 +0,0 @@");
} else if (unifiedDiff.size() >= 3 && !unifiedDiff.get(2).contains("@@ -1,")) {
//如果第一行没变化则插入@@ -0,0 +0,0 @@
unifiedDiff.add(2, "@@ -0,0 +0,0 @@");
}
//原始文件中每行前加空格
List original1 = original.stream().map(v -> " " + v).collect(Collectors.toList());
//差异格式插入到原始文件中
return insertOrig(original1, unifiedDiff);
}
public static List diffString(String filePathOriginal, String filePathRevised) {
//原始文件
List original = null;
//对比文件
List revised = null;
File originalFile = new File(filePathOriginal);
File revisedFile = new File(filePathRevised);
try {
original = Files.readAllLines(originalFile.toPath());
revised = Files.readAllLines(revisedFile.toPath());
} catch (IOException e) {
e.printStackTrace();
}
return diffString(original, revised, originalFile.getName(), revisedFile.getName());
}
//统一差异格式插入到原始文件
public static List insertOrig(List original, List unifiedDiff) {
List result = new ArrayList<>();
//unifiedDiff中根据@@分割成不同行,然后加入到diffList中
List> diffList = new ArrayList<>();
List d = new ArrayList<>();
for (int i = 0; i < unifiedDiff.size(); i++) {
String u = unifiedDiff.get(i);
if (u.startsWith("@@") && !"@@ -0,0 +0,0 @@".equals(u) && !u.contains("@@ -1,")) {
List twoList = new ArrayList<>();
twoList.addAll(d);
diffList.add(twoList);
d.clear();
d.add(u);
continue;
}
if (i == unifiedDiff.size() - 1) {
d.add(u);
List twoList = new ArrayList<>();
twoList.addAll(d);
diffList.add(twoList);
d.clear();
break;
}
d.add(u);
}
//将diffList和原始文件original插入到result,返回result
for (int i = 0; i < diffList.size(); i++) {
List diff = diffList.get(i);
List nexDiff = i == diffList.size() - 1 ? null : diffList.get(i + 1);
//含有@@的一行
String simb = i == 0 ? diff.get(2) : diff.get(0);
String nexSimb = nexDiff == null ? null : nexDiff.get(0);
//插入到result
insert(result, diff);
//解析含有@@的行,得到原文件从第几行开始改变,改变了多少(即增加和减少的行)
Map map = getRowMap(simb);
if (null != nexSimb) {
Map nexMap = getRowMap(nexSimb);
int start = 0;
if (map.get("orgRow") != 0) {
start = map.get("orgRow") + map.get("orgDel") - 1;
}
int end = nexMap.get("revRow") - 2;
//插入不变的
insert(result, getOrigList(original, start, end));
}
if (simb.contains("@@ -1,") && null == nexSimb) {
insert(result, getOrigList(original, 0, original.size() - 1));
} else if (null == nexSimb && map.get("orgRow") < original.size()) {
insert(result, getOrigList(original, map.get("orgRow"), original.size() - 1));
}
}
return result;
}
//将源文件中没变的内容插入result
public static void insert(List result, List noChangeContent) {
for (String ins : noChangeContent) {
result.add(ins);
}
}
//解析含有@@的行得到修改的行号删除或新增了几行
public static Map getRowMap(String str) {
Map map = new HashMap<>();
if (str.startsWith("@@")) {
String[] sp = str.split(" ");
String org = sp[1];
String[] orgSp = org.split(",");
//源文件要删除行的行号
map.put("orgRow", Integer.valueOf(orgSp[0].substring(1)));
//源文件删除的行数
map.put("orgDel", Integer.valueOf(orgSp[1]));
String[] revSp = org.split(",");
//对比文件要增加行的行号
map.put("revRow", Integer.valueOf(revSp[0].substring(1)));
map.put("revAdd", Integer.valueOf(revSp[1]));
}
return map;
}
//从原文件中获取指定的部分行
public static List getOrigList(List original1, int start, int end) {
List list = new ArrayList<>();
if (start <= end && end < original1.size()) {
for (; start <= end; start++) {
list.add(original1.get(start));
}
}
return list;
}
}
测试:
public static void main(String[] args) throws IOException, PatchFailedException {
List diffString = DiffHandleUtils.diffString("D:\test5.txt","D:\test6.txt");
diffString.forEach(System.out::println);
}
输出;
--- test5.txt +++ test6.txt @@ -1,1 +1,3 @@ -1111 + +aaaa +bbbb 2222 @@ -3,1 +5,1 @@ -3333 +3 4444 @@ -5,1 +7,1 @@ -5555 +5555qqqq 6666 @@ -7,1 +9,1 @@ -7777 + 8888 9999 @@ -10,0 +12,2 @@ +xxxx +cccc三、前端实现
把上面获取到的 diffString 粘贴到下面html的 diffString 中
浏览器打开html效果如下:



