Подтвердить что ты не робот

Создание форматированного вывода diff в Java

Есть ли там библиотеки для 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.

4b9b3361

Ответ 1

Я закончил свой собственный. Не уверен, что это лучшая реализация, и это уродливо, как черт, но оно проходит против тестового ввода.

Он использует 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");
    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;
}

Ответ 2

java-diff-utils

Библиотека DiffUtils для вычислений diffs, применение патчей, generationg бок о бок в Java

Библиотека Diff Utils - это OpenSource библиотека для сравнения операции между текстами: вычисление разграничивает, применяет исправления, генерирует унифицированные различия или разбор их, генерация разностной мощности для легкого будущего отображение (например, бок о бок) и т.д.

Основная причина создания этой библиотеки - отсутствие простых в использовании библиотек с все обычные вещи, которые вам нужны во время работа с файлами diff. Первоначально была вдохновлена ​​библиотекой JRCS, и хороший дизайн диффузионного модуля.

Основные функции

  • вычисление разницы между двумя текстами.
  • способен передавать больше, чем простой ascci. Массивы или список любого типа, который реализует hashCode() и equals() правильно может быть различие с использованием этой библиотеки
  • патч и распаковка текста с данным патчем
  • синтаксический анализ унифицированного формата diff
  • создание различий, понятных человеку.

Ответ 3

Busybox имеет реализацию diff, которая очень скудная, не должна быть трудно конвертировать в java, но вам придется добавить функциональность с двумя столбцами.

Ответ 4

http://c2.com/cgi/wiki?DiffAlgorithm Я нашел это в Google, и это дает хороший фон и ссылки. Если вам небезразличен алгоритм, выходящий за рамки простого проекта, книга об основном алгоритме, который охватывает динамическое программирование или книгу на нем. Знание алгоритма всегда хорошо:)

Ответ 5

Для этого вы можете использовать библиотеку Apache Commons Text. Эта библиотека предоставляет возможность 'diff', основанную на "очень эффективном алгоритме от Eugene W. Myers".

Это дает вам возможность создать своего собственного посетителя, чтобы вы могли обрабатывать diff по своему усмотрению, а также выводить его на консоль, HTML и т.д. Вот одна статья, в которой дается простой и удобный пример вывода бок о бок diff в HTML формат с использованием Apache Commons Текстовая библиотека и простой код Java.