当前位置: 首页 > 面试题库 >

用Java生成格式化的差异输出

秋和雅
2023-03-14
问题内容

是否有任何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可用。


问题答案:

我最终自己动手了。不知道这是否是最好的实现,而且很难看,但是它会传递给测试输入。

它使用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;
}


 类似资料:
  • 我们可以看到格式化就是通过格式字符串得到特定格式: format!("{}", foo) -> "3735928559" format!("0x{:X}", foo) -> "0xDEADBEEF" format!("0o{:o}", foo) -> "0o33653337357" 根据使用的参数类型,同样的变量(foo)能够格式化成不同的形式:X, o 和未指定形式。 这个格式化的功能是通过 t

  • 我试图在Windows上使用BCP(版本10)将数据导入赛贝斯ASE 15.7(试用版)。为此,我首先尝试使用以下命令为表创建格式文件,并获得一个错误:复制方向必须是in或out。格式中的语法错误。 我在下面的站点上查找了BCP实用程序选项,发现没有列出创建格式文件或queryout的选项。http://infocenter.sybase.com/help/index.jsp?topic=/com

  • 本文向大家介绍浅谈Java中格式化输出,包括了浅谈Java中格式化输出的使用技巧和注意事项,需要的朋友参考一下 格式化控制台输出 要点提示: 在控制台上显示格式化输出:System.out.printf方法 常用的格式标识符 (图片来源: java核心技术卷1(第九版)) 格式标识符的解释 % 4 . 2 f 4为域宽度.输出的浮点数条目宽度至少为4,包括小数点和小数点后两位数字.这样,给小数点前

  • 我正在尝试用Java从System.out.println中打印一些ASCII图片。当我这样做的时候,源代码中所有的空格都消失了。打印出来的是一堆没有任何意义的废话。图1显示了源代码的样子和ASCII艺术应该是什么样子。图2显示了程序运行时横幅的实际外观。 我的问题是如何按预期打印ASCII艺术?我如何使用使横幅可读的格式打印ASCII艺术? 例如,使用Python,我可以通过使用三重引号轻松完成

  • 主要内容:实例,实例,格式变量,实例,实例,实例,实例,输出到其它文件,实例,实例Perl 是一个非常强大的文本数据处理语言。 Perl 中可以使用 format 来定义一个模板,然后使用 write 按指定模板输出数据。 Perl 格式化定义语法格式如下: 参数解析: FormatName :格式化名称。 fieldline :一个格式行,用来定义一个输出行的格式,类似 @,^,<,>,| 这样的字符。 value_one,value_two…… :数据行,用来向前面的格式行

  • 主要内容:实例,运行实例标签呈现HTML文本,但可以接受参数化输入。 以下JSF代码 - 被渲染成以下HTML代码 - 实例 打开NetBean8.2,创建一个名称为:OutputFormat 的JavaWeb JSF工程。以下是文件:UserBean.java中的代码 - 以下是文件:index.xhtml中的代码 - 运行实例 Tomcat启动完成后,在浏览器地址栏中输入以下URL。 得到结果如下图所示 -