maven依赖
<dependency>
<groupId>io.github.java-diff-utils</groupId>
<artifactId>java-diff-utils</artifactId>
<version>4.11</version>
</dependency>
创建Diff 工具类
package com.system.utlis.diff;
import com.github.difflib.UnifiedDiffUtils;
import com.github.difflib.patch.Patch;
import org.springframework.stereotype.Component;
import java.io.*;
import java.nio.charset.StandardCharsets;
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;
@Component
public class DiffHandleUtils {
public static void main(String[] args) {
List<String> diffString = DiffHandleUtils.diffString("E:\\test\\test1.java", "E:\\test\\test2.txt");
DiffHandleUtils.generateDiffHtml(diffString, "E:\\test");
System.out.println("diff完成");
}
public static List<String> diffString(List<String> original, List<String> revised) {
return diffString(original, revised, null, null);
}
public static List<String> diffString(List<String> original, List<String> revised, String originalFileName, String revisedFileName) {
originalFileName = originalFileName == null ? "原始文件" : originalFileName;
revisedFileName = revisedFileName == null ? "对比文件" : revisedFileName;
Patch<String> patch = com.github.difflib.DiffUtils.diff(original, revised);
List<String> unifiedDiff = UnifiedDiffUtils.generateUnifiedDiff(originalFileName, revisedFileName, original, patch, 0);
int diffCount = unifiedDiff.size();
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,")) {
unifiedDiff.set(1, unifiedDiff.get(1));
unifiedDiff.add(2, "@@ -0,0 +0,0 @@");
}
List<String> original1 = original.stream().map(v -> " " + v).collect(Collectors.toList());
return insertOrig(original1, unifiedDiff);
}
public static List<String> diffString(String filePathOriginal, String filePathRevised) {
List<String> original = null;
List<String> 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 void generateDiffHtml(List<String> diffString, String htmlPath) {
StringBuilder builder = new StringBuilder();
for (String line : diffString) {
builder.append(escapeStr(line));
builder.append("\n");
}
String githubCss = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.1/styles/github.min.css";
String diff2htmlCss = "https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css";
String diff2htmlJs = "https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js";
String template = "<!DOCTYPE html>\n" +
"<html lang=\"en-us\">\n" +
" <head>\n" +
" <meta charset=\"utf-8\" />\n" +
" <link rel=\"stylesheet\" href=\"" + githubCss + "\" />\n" +
" <link rel=\"stylesheet\" type=\"text/css\" href=\"" + diff2htmlCss + "\" />\n" +
" <script type=\"text/javascript\" src=\"" + diff2htmlJs + "\"></script>\n" +
" </head>\n" +
" <script>\n" +
" const diffString = `\n" +
"temp\n" +
"`;\n" +
"\n" +
"\n" +
" document.addEventListener('DOMContentLoaded', function () {\n" +
" var targetElement = document.getElementById('myDiffElement');\n" +
" var configuration = {\n" +
" drawFileList: true,\n" +
" fileListToggle: true,\n" +
" fileListStartVisible: true,\n" +
" fileContentToggle: true,\n" +
" matching: 'lines',\n" +
" outputFormat: 'side-by-side',\n" +
" synchronisedScroll: true,\n" +
" highlight: true,\n" +
" renderNothingWhenEmpty: true,\n" +
" };\n" +
" var diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);\n" +
" diff2htmlUi.draw();\n" +
" diff2htmlUi.highlightCode();\n" +
" });\n" +
" </script>\n" +
" <body>\n" +
" <div id=\"myDiffElement\"></div>\n" +
" </body>\n" +
"</html>";
template = template.replace("temp", builder.toString());
File f = null;
File folder = new File(htmlPath);
if (!folder.exists() && !folder.isDirectory()) {
folder.mkdirs();
}
try {
f = new File(htmlPath + "diff.html");
BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8));
buf.write(template);
buf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static String escapeStr(String linStr) {
if (linStr.contains("\\")) {
linStr = linStr.replaceAll("\\\\", "\\\\\\\\");
}
if (linStr.contains("</script>")) {
linStr = linStr.replaceAll("</script>", "<\\\\/script>");
}
if (linStr.contains("`")) {
linStr = linStr.replaceAll("`", "\\\\`");
}
if (linStr.contains("$")) {
linStr = linStr.replaceAll("\\$", "\\\\\\$");
}
return linStr;
}
public static List<String> insertOrig(List<String> original, List<String> unifiedDiff) {
List<String> result = new ArrayList<>();
List<List<String>> diffList = new ArrayList<>();
List<String> 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<String> twoList = new ArrayList<>();
twoList.addAll(d);
diffList.add(twoList);
d.clear();
d.add(u);
continue;
}
if (i == unifiedDiff.size() - 1) {
d.add(u);
List<String> twoList = new ArrayList<>();
twoList.addAll(d);
diffList.add(twoList);
d.clear();
break;
}
d.add(u);
}
for (int i = 0; i < diffList.size(); i++) {
List<String> diff = diffList.get(i);
List<String> 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);
insert(result, diff);
Map<String, Integer> map = getRowMap(simb);
if (null != nexSimb) {
Map<String, Integer> 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));
}
int start = (map.get("orgRow") + map.get("orgDel") - 1);
start = start == -1 ? 0 : start;
if (simb.contains("@@ -1,") && null == nexSimb && map.get("orgDel") != original.size()) {
insert(result, getOrigList(original, start, original.size() - 1));
} else if (null == nexSimb && (map.get("orgRow") + map.get("orgDel") - 1) < original.size()) {
insert(result, getOrigList(original, start, original.size() - 1));
}
}
int diffCount = diffList.size() - 1;
if (!"@@ -0,0 +0,0 @@".equals(unifiedDiff.get(2))) {
diffCount = diffList.size() > 1 ? diffList.size() : 1;
}
result.set(1, result.get(1) + " ( " + diffCount + " different )");
return result;
}
public static void insert(List<String> result, List<String> noChangeContent) {
for (String ins : noChangeContent) {
result.add(ins);
}
}
public static Map<String, Integer> getRowMap(String str) {
Map<String, Integer> 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<String> getOrigList(List<String> original1, int start, int end) {
List<String> list = new ArrayList<>();
if (original1.size() >= 1 && start <= end && end < original1.size()) {
for (; start <= end; start++) {
list.add(original1.get(start));
}
}
return list;
}
}
测试效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5de5e3691942b5cecbc6adb89717db24.png)