Существуют ли какие-либо библиотеки для 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.




Busybox имеет очень простую реализацию diff, которую не составит труда преобразовать в java, но вам придется добавить функциональность с двумя столбцами.
http://c2.com/cgi/wiki?DiffAlgorithm Я нашел это в Google, и там есть хорошая справочная информация и ссылки. Если вам важен алгоритм, помимо выполнения проекта, книга по базовым алгоритмам, охватывающая динамическое программирование, или книга только по нему. Знание алгоритмов всегда хорошо :)
В конце концов я закрутил свой собственный. Не уверен, что это лучшая реализация, и она чертовски уродлива, но она проходит против тестового ввода.
Он использует java-diff для тяжелого подъема различий (любые общие Apache 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");
List<Difference> diffs = (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;
}
Можете ли вы опубликовать max Length () и значение NONE? Спасибо, что сэкономили мне массу разработок
Вам нужна библиотека java-diff-utils? Просто хочу знать (простите за каламбур).
The DiffUtils library for computing diffs, applying patches, generationg side-by-side view in Java
Diff Utils library is an OpenSource library for performing the comparison operations between texts: computing diffs, applying patches, generating unified diffs or parsing them, generating diff output for easy future displaying (like side-by-side view) and so on.
Main reason to build this library was the lack of easy-to-use libraries with all the usual stuff you need while working with diff files. Originally it was inspired by JRCS library and it's nice design of diff module.
Main Features
- computing the difference between two texts.
- capable to hand more than plain ascci. Arrays or List of any type that implements hashCode() and equals() correctly can be subject to differencing using this library
- patch and unpatch the text with the given patch
- parsing the unified diff format
- producing human-readable differences
Активно поддерживаемый форк выглядит как github.com/bkromhout/java-diff-utils
producing human-readable differences. Это уже сделано? не могли бы вы указать мне на пример.
Для этого вы можете использовать библиотеку Текст Apache Commons. Эта библиотека предоставляет возможность 'diff', основанную на "очень эффективном алгоритме Юджина В. Майерса".
Это дает вам возможность создать своего собственного посетителя, чтобы вы могли обрабатывать разницу так, как вы хотите, и можно было выводить на консоль или HTML и т. д. Вот одна статья, которая проходит через хороший и простой пример вывода параллельных различий в формате HTML с использованием текстовой библиотеки Apache Commons и простого кода Java.
Получение рабочих реализаций на Java - простая часть - они уже есть. Жесткий бит на самом деле форматировал вывод в требуемый формат.