Создание форматированного вывода 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.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
21
0
23 428
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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

Получение рабочих реализаций на Java - простая часть - они уже есть. Жесткий бит на самом деле форматировал вывод в требуемый формат.

madlep 26.11.2008 08:45
Ответ принят как подходящий

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

Он использует 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? Спасибо, что сэкономили мне массу разработок

Bostone 13.11.2010 00:28

Вам нужна библиотека java-diff-utils? Просто хочу знать (простите за каламбур).

Marcus Junius Brutus 15.11.2013 21:34

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

koppor 23.11.2016 09:55
producing human-readable differences. Это уже сделано? не могли бы вы указать мне на пример.
Prakash Palnati 03.09.2018 20:20

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

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

Другие вопросы по теме