java 最长公共字符算法实现文档内容字符串对比并返回差异html
1. 读取docx文档
使用POI进行文档的读取
/**
* 获取文档内容
* @param path 文档磁盘路径
* @throws IOException
*/
private StringBuilder getDocText(String path ) throws IOException {
StringBuilder builder= new StringBuilder();
XWPFDocument doc = new XWPFDocument(new FileInputStream(path));
List<IBodyElement> elements = doc.getBodyElements();
for (IBodyElement element : elements) {
// 段落
if (element instanceof XWPFParagraph) {
XWPFParagraph paragraph = (XWPFParagraph) element;
List<XWPFRun> runs = paragraph.getRuns();
//空行用标签换行
if (runs.size() == 0) {
builder.append("<br>");
}
for (XWPFRun run : runs) {
builder.append(run.text());
}
}// 表格
else if (element instanceof XWPFTable) {
XWPFTable table= (XWPFTable) element;
// 获取每个单元格
List<XWPFTableRow> rows = table.getRows();
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
// 一个单元格可以理解为一个word文档,单元格里也可以加段落与表格
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
//空单元格用空格代替
if (runs.size() == 0) {
builder.append(" ");
}
for (XWPFRun run : runs) {
builder.append(run.text()+" ");
}
}
}
//每行加个换行标签
builder.append("<br>");
}
}
}
return builder;
}
2. 查找最长公共子串
该方法引用自:Java算法——求出两个字符串的最长公共字符串 - 春秋阕 - 博客园 (cnblogs.com)
/**
* 查找最长公共字符算法
* @param str1
* @param str2
* @return
*/
private StringBuilder maxUtil2(String str1, String str2) {
//把字符串转成字符数组
char[] arr1 = str1.toCharArray();
char[] arr2 = str2.toCharArray();
// 把两个字符串分别以行和列组成一个二维矩阵
int[][] temp = new int[arr1.length][arr2.length];
// 存储最长公共子串长度
int length = 0;
//start表明最长公共子串的起始点,end表明最长公共子串的终止点
int end = 0;
int start = 0;
初始化二维矩阵中的第一行
for (int i = 0; i < arr2.length; i++) {
temp[0][i] = (arr1[0] == arr2[i]) ? 1 : 0;
}
//初始化二维矩阵中的第一列
for (int j = 0; j < arr1.length; j++) {
temp[j][0] = (arr2[0] == arr1[j]) ? 1 : 0;
}
//嵌套for循环:比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0
for (int i = 1; i < arr1.length; i++) {
for (int j = 1; j < arr2.length; j++) {
if (arr1[i] == arr2[j]) {
temp[i][j] = temp[i - 1][j - 1] + 1;
if (temp[i][j] > length) {
length = temp[i][j];
end = j;
}
} else
temp[i][j] = 0;
}
}
//求出最长公共子串的起始点
start=end-length+1;
StringBuilder sb=new StringBuilder();
//通过查找出值为1的最长对角线就能找到最长公共子串
for (int j = start; j < end+1; j++) {
sb.append(arr2[j]);
}
return sb;
}
3. 代码实现
@Data
@AllArgsConstructor
public class DiffObject {
/**
* 公共子串
*/
private String name;
/**
* 起始位置
*/
private Integer index;
}
调用方法代码实现
public static void main(String[] args) {
//返回新旧文本的html的map对象
HashMap<String, String> map = new HashMap<String, String>();
//获取文件保存路径
String oldUrl="C:/Users/12855/Desktop/1.docx";
String newUrl="C:/Users/12855/Desktop/2.docx";
//原始文件内容
StringBuilder oldText = null;
//最新文件内容
StringBuilder newText = null;
try {
//获取文档内容
oldText= getDocText(oldUrl);
newText= getDocText(newUrl);
} catch (IOException e) {
e.printStackTrace();
}
// 随机生成字符串
String strOne = oldText.toString();
String strTwo = newText.toString();
//遍历查询到的文档名字
ArrayList<DiffObject> demotes = new ArrayList<DiffObject>();
while (true) {
//获取最长公共子串
String same = maxUtil2(strOne, strTwo).toString();
if (same.length() <= 0) {
break;
}
demotes.add(new DiffObject(same,strTwo.indexOf(same)));
strOne= strOne.replace(same,"-");
strTwo= strTwo.replace(same,"*");
}
String div="<span style=\"background-color: yellow\">"+newText.toString()+"</span>";
for (DiffObject demote : demotes) {
div= div.replace(demote.getName(),"<span style=\"background-color: white\">"+demote.getName()+"</span>");
}
map.put("oldHtml",oldText.toString());
map.put("newHtml",div);
System.out.println(map.get("oldHtml"));
System.out.println(map.get("newHtml"));
}
4. 测试文件
1.docx
根据气象部门的预报,河北中部、四川盆地西部、贵州西部、湖北中部和东南部、湖南北部、江苏中部、江西中部等地部分地区有大雾。
而内蒙古东北部、黑龙江西北部、新疆南疆西部、西藏大部、青海南部等地部分地区有小到中雪或雨夹雪。下雪天气主要分布在西部高寒地区,还有就是零星分布在北方和东北地区,对于全国影响不大。而下雨地区也是在西南地区,如西藏东南部、四川盆地西部、贵州中西部、云南东部等地有小雨。
标题1 标题2 标题3 标题4 标题5
而内蒙 北 江西 南疆 藏大
星分 东北 全国影 雨 州中
有小 零星 东北 区 西中
2.docx
根据气象部门的预报,河北中部、四川方和西部、贵州西部、湖北中部和东南部、湖南北部、江苏中部、江西中部等地部分地区有大雾。
而内蒙得到部、黑龙江西北部、新疆西部、西藏大部、青海间距地部分地方和小到中雪或雨夹雪。下雪天气主要分布间距高寒地区,还有就是零星分布行方和东北地区,对2更方和影响不大。而44下雨地区也是在西南地区,如东南部、四川5u盆地西部、贵州中西部、云南东方和地有小雨。
标题1 标题2 标题3 标题4 标题5
而内蒙 北 江西 南疆 藏大
星分 东中雪或北 对于全国 雨天 零星
而内蒙 零星 东北江西 藏大 西中
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
<el-row :gutter="24">
<el-col :span="12"><div class="grid-content bg-purple" style="font-size: 18px">
最新版本:
</div></el-col>
<el-col :span="12"><div class="grid-content bg-purple" style="font-size: 18px">
历史版本:
</div></el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12"><div class="grid-content bg-purple">
<div style="border: 1px #8EB9B9 solid; margin: 20px 20px 20px 20px;padding: 20px 20px 20px 20px;overflow-y:scroll; height: 600px" v-html="oldHtml"></div>
</div></el-col>
<el-col :span="12"><div class="grid-content bg-purple">
<div style="border: 1px #8EB9B9 solid; margin: 20px 20px 20px 20px;padding: 20px 20px 20px 20px;overflow-y:scroll; height: 600px" v-html="newHtml"></div>
</div></el-col>
</el-row>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
el: '#app',
data: function() {
return {
oldHtml:'根据气象部门的预报,河北中部、四川盆地西部、贵州西部、湖北中部和东南部、湖南北部、江苏中部、江西中部等地部分地区有大雾。而内蒙古东北部、黑龙江西北部、新疆南疆西部、西藏大部、青海南部等地部分地区有小到中雪或雨夹雪。下雪天气主要分布在西部高寒地区,还有就是零星分布在北方和东北地区,对于全国影响不大。而下雨地区也是在西南地区,如西藏东南部、四川盆地西部、贵州中西部、云南东部等地有小雨。标题1 标题 2 标题 3 标题 4 标题 5 <br>而内蒙 北 江西 南疆 藏大 <br>星分 东北 全国影 雨 州中 <br>有小 零星 东北 区 西中 <br><br>',
newHtml:'<span style="background-color: yellow"><span style="background-color: white">根据气象部门的预报,河北<span style="background-color: white">中</span>部、四川</span>方和<span style="background-color: white"><span style="background-color: white">西</span>部、贵州<span style="background-color: white">西</span>部、湖北<span style="background-color: white">中</span>部和东南部、湖南北部、江苏<span style="background-color: white">中</span>部、江<span style="background-color: white">西</span><span style="background-color: white">中</span>部等<span style="background-color: white">地部分地</span>区有大雾。而内蒙</span>得到<span style="background-color: white">部、黑龙江<span style="background-color: white">西</span>北部、新疆</span><span style="background-color: white"><span style="background-color: white">西</span>部、<span style="background-color: white">西</span><span style="background-color: white">藏</span>大部、青海</span>间距<span style="background-color: white">地部分地</span>方和<span style="background-color: white">小到<span style="background-color: white">中</span>雪或雨夹雪。下雪天气主要分布</span>间距<span style="background-color: white">高寒地区,还有就是零星分布</span>行<span style="background-color: white">方和东北地区,对</span>2更方和<span style="background-color: white">影响不大。而</span>44<span style="background-color: white">下雨地区也是在<span style="background-color: white">西</span>南地区,如</span><span style="background-color: white">东南部、四川</span>5u<span style="background-color: white">盆地<span style="background-color: white">西</span>部、贵州<span style="background-color: white">中</span><span style="background-color: white">西</span>部、云南东</span>方和<span style="background-color: white">地有小雨。标题1 标题 2 标题 3 标题 4 标题 5<span style="background-color: white"> <br></span>而内蒙 <span style="background-color: white">北 </span>江<span style="background-color: white">西</span> 南疆 <span style="background-color: white">藏</span>大<span style="background-color: white"> <br></span>星分 东</span> <span style="background-color: white">中</span>雪或 <span style="background-color: white">北 </span>对<span style="background-color: white">于全国</span><span style="background-color: white"> 雨 </span>天 零星<span style="background-color: white"> <br></span>而内蒙<span style="background-color: white"> 零星 东<span style="background-color: white">北 </span></span>江<span style="background-color: white">西</span> <span style="background-color: white">藏</span>大<span style="background-color: white"> <span style="background-color: white">西</span><span style="background-color: white">中</span><span style="background-color: white"> <br></span><br></span></span>'
}
}
})
</script>
</html>