是否有任何Java库可以接受两个字符串,并根据*nix diff命令返回带格式化输出的字符串?
例如,进食
test 1,2,3,4 test 5,6,7,8 test 9,10,11,12 test 13,14,15,16
和
test 1,2,3,4 test 5,6,7,8 test 9,10,11,12,13 test 13,14,15,16
作为输入,它会给你
test 1,2,3,4 test 1,2,3,4 test 5,6,7,8 test 5,6,7,8 test 9,10,11,12 | test 9,10,11,12,13 test 13,14,15,16 test 13,14,15,16
与我传递文件完全相同 diff -y expected actual
我发现了这个问题,它为一般库提供了一些很好的建议,为你提供程序化输出,但我想要直接的字符串结果.
我可以diff
直接调用系统调用,但这个特定的应用程序将在unix和windows上运行,我不能确定环境实际上是否diff
可用.
DiffUtils库用于计算差异,应用补丁,生成Java中的并排视图
Diff Utils库是一个OpenSource库,用于执行文本之间的比较操作:计算差异,应用补丁,生成统一差异或解析它们,生成差异输出以便于将来显示(如并排视图)等.
构建这个库的主要原因是缺少易于使用的库,其中包含处理diff文件时所需的所有常用内容.最初它的灵感来自JRCS库,它是diff模块的好设计.
主要特点
计算两个文本之间的差异.
能比普通的ascci更有能力.正确实现hashCode()和equals()的任何类型的数组或列表都可以使用此库进行差分
使用给定的补丁修补和取消文本
解析统一的diff格式
产生人类可读的差异
我最终滚动了自己.不确定它是否是最好的实现,并且它很丑陋,但它会通过测试输入.
它使用java-diff来进行重度差异提升(任何apache commons StrBuilder和StringUtils而不是库存Java StringBuilder)
public static String diffSideBySide(String fromStr, String toStr){ // this is equivalent of running unix diff -y command // not pretty, but it works. Feel free to refactor against unit test. String[] fromLines = fromStr.split("\n"); String[] toLines = toStr.split("\n"); Listdiffs = (new Diff(fromLines, toLines)).diff(); int padding = 3; int maxStrWidth = Math.max(maxLength(fromLines), maxLength(toLines)) + padding; StrBuilder diffOut = new StrBuilder(); diffOut.setNewLineText("\n"); int fromLineNum = 0; int toLineNum = 0; for(Difference diff : diffs) { int delStart = diff.getDeletedStart(); int delEnd = diff.getDeletedEnd(); int addStart = diff.getAddedStart(); int addEnd = diff.getAddedEnd(); boolean isAdd = (delEnd == Difference.NONE && addEnd != Difference.NONE); boolean isDel = (addEnd == Difference.NONE && delEnd != Difference.NONE); boolean isMod = (delEnd != Difference.NONE && addEnd != Difference.NONE); //write out unchanged lines between diffs while(true) { String left = ""; String right = ""; if (fromLineNum < (delStart)){ left = fromLines[fromLineNum]; fromLineNum++; } if (toLineNum < (addStart)) { right = toLines[toLineNum]; toLineNum++; } diffOut.append(StringUtils.rightPad(left, maxStrWidth)); diffOut.append(" "); // no operator to display diffOut.appendln(right); if( (fromLineNum == (delStart)) && (toLineNum == (addStart))) { break; } } if (isDel) { //write out a deletion for(int i=delStart; i <= delEnd; i++) { diffOut.append(StringUtils.rightPad(fromLines[i], maxStrWidth)); diffOut.appendln("<"); } fromLineNum = delEnd + 1; } else if (isAdd) { //write out an addition for(int i=addStart; i <= addEnd; i++) { diffOut.append(StringUtils.rightPad("", maxStrWidth)); diffOut.append("> "); diffOut.appendln(toLines[i]); } toLineNum = addEnd + 1; } else if (isMod) { // write out a modification while(true){ String left = ""; String right = ""; if (fromLineNum <= (delEnd)){ left = fromLines[fromLineNum]; fromLineNum++; } if (toLineNum <= (addEnd)) { right = toLines[toLineNum]; toLineNum++; } diffOut.append(StringUtils.rightPad(left, maxStrWidth)); diffOut.append("| "); diffOut.appendln(right); if( (fromLineNum > (delEnd)) && (toLineNum > (addEnd))) { break; } } } } //we've finished displaying the diffs, now we just need to run out all the remaining unchanged lines while(true) { String left = ""; String right = ""; if (fromLineNum < (fromLines.length)){ left = fromLines[fromLineNum]; fromLineNum++; } if (toLineNum < (toLines.length)) { right = toLines[toLineNum]; toLineNum++; } diffOut.append(StringUtils.rightPad(left, maxStrWidth)); diffOut.append(" "); // no operator to display diffOut.appendln(right); if( (fromLineNum == (fromLines.length)) && (toLineNum == (toLines.length))) { break; } } return diffOut.toString(); } private static int maxLength(String[] fromLines) { int maxLength = 0; for (int i = 0; i < fromLines.length; i++) { if (fromLines[i].length() > maxLength) { maxLength = fromLines[i].length(); } } return maxLength; }