21

2 つの文字列を受け入れ、*nix diff コマンドに従って書式設定された出力を含む文字列を返す Java 用のライブラリはありますか?

例:フィードイン

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ん。

4

5 に答える 5

15

java-diff-utils

差分の計算、パッチの適用、Javaでの生成を並べて表示するためのDiffUtilsライブラリ

Diff Utilsライブラリは、テキスト間の比較操作を実行するためのオープンソースライブラリです。差分の計算、パッチの適用、統一された差分の生成または解析、将来の表示(サイドバイサイドビューなど)のための差分出力の生成などです。

このライブラリを構築する主な理由は、diffファイルでの作業中に必要なすべての通常のものを備えた使いやすいライブラリがないことでした。もともとはJRCSライブラリに触発されており、diffモジュールの素晴らしいデザインです。

主な特徴

  • 2つのテキストの違いを計算します。
  • 普通のascci以上のものを渡すことができます。hashCode()およびequals()を正しく実装する任意のタイプの配列またはリストは、このライブラリを使用して差分の対象となる可能性があります
  • 指定されたパッチでテキストにパッチを適用し、パッチを解除します
  • 統一されたdiff形式の解析
  • 人間が読める形式の違いを生み出す
于 2011-02-24T14:39:49.510 に答える
6

私は自分自身を転がすことになった。それが最良の実装であるかどうかはわかりませんし、地獄のように醜いですが、テスト入力に対しては合格です。

java-diffを使用して、重い差分リフティングを行います (ストック Java StringBuilder の代わりに、Apache Commons StrBuilder および StringUtils を使用します)。

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;
}
于 2008-11-26T05:42:50.203 に答える
0

Busybox には非常に無駄のない差分実装があり、Java に変換するのは難しくありませんが、2 列の機能を追加する必要があります。

于 2008-11-26T01:31:34.190 に答える
0

http://c2.com/cgi/wiki?DiffAlgorithmこれは Google で見つけたもので、良い背景とリンクがいくつかあります。プロジェクトを実行するだけでなくアルゴリズムに関心がある場合は、動的プログラミングをカバーする基本的なアルゴリズムに関する本、またはそれに関する本を読んでください。アルゴリズムの知識は常に良いです:)

于 2008-11-26T01:59:39.907 に答える