2008-11-26 40 views
17

Có thư viện nào ở đó cho Java chấp nhận hai chuỗi và trả về một chuỗi có đầu ra được định dạng theo lệnh * nix diff không?Tạo đầu ra diff được định dạng trong Java

ví dụ: nuôi trong

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 

như đầu vào, và nó sẽ cung cấp cho bạn

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 

Chính xác giống như nếu tôi đã vượt qua các tập tin để diff -y expected actual

tôi thấy this question, và nó đưa ra một số lời khuyên tốt về các thư viện chung cho bạn p đầu ra rogrammatic, nhưng tôi muốn kết quả chuỗi thẳng.

Tôi có thể gọi diff trực tiếp dưới dạng cuộc gọi hệ thống, nhưng ứng dụng cụ thể này sẽ chạy trên Unix và cửa sổ và tôi không thể chắc chắn rằng môi trường sẽ thực sự có sẵn diff.

Trả lời

6

Tôi đã kết thúc bằng việc tự tạo. Bạn không chắc đó có phải là triển khai tốt nhất hay không và nó xấu xí như địa ngục, nhưng nó vượt qua kiểm tra đầu vào.

Nó sử dụng java-diff để làm việc nặng nhọc khác (bất kỳ commons apache StrBuilder và StringUtils thay vì cổ phiếu 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; 
} 
+0

Bạn có thể đăng giá trị maxLength() amd của NONE không? Cảm ơn bạn đã tiết kiệm cho tôi rất nhiều sự phát triển – Bostone

+0

Bạn có tìm thấy thư viện java-diff-utils mong muốn không? Chỉ muốn biết (lý do chơi chữ). –

0

Busybox có triển khai khác biệt rất gọn gàng, không khó để chuyển đổi sang java, nhưng bạn sẽ phải thêm chức năng hai cột.

0

http://c2.com/cgi/wiki?DiffAlgorithm Tôi tìm thấy điều này trên Google và nó cung cấp một số nền tảng và liên kết tốt. Nếu bạn quan tâm đến thuật toán ngoài việc thực hiện dự án, một cuốn sách về thuật toán cơ bản bao gồm Lập trình động hoặc một cuốn sách ngay trên đó. Kiến thức về thuật toán luôn tốt :)

+0

Việc triển khai thực hiện trong Java là phần dễ dàng - chúng ở ngoài đó. Bit cứng thực sự định dạng đầu ra theo định dạng được yêu cầu. – madlep

14

java-diff-utils

Thư viện DiffUtils để tính diffs, áp dụng các bản vá lỗi , generationg chế độ xem song song trong Java

Thư viện Diff Utils là một OpenSource thư viện để thực hiện việc so sánh hoạt động giữa các văn bản: tính toán diffs, áp dụng các bản vá lỗi, tạo ra diffs thống nhất hoặc phân tích chúng, tạo ra khác để dễ dàng trong tương lai hiển thị (như side-by-side view) và vân vân.

Lý do chính để xây dựng thư viện này là thiếu thư viện dễ sử dụng với tất cả những thứ thông thường bạn cần trong khi làm việc với các tập tin khác. Ban đầu nó được lấy cảm hứng từ thư viện JRCS và nó là thiết kế đẹp của mô-đun khác.

Tính năng chính

  • tính toán sự khác biệt giữa hai văn bản.
  • có khả năng trao nhiều hơn ascci đơn giản. Mảng hoặc Danh sách của bất kỳ loại mà thực hiện hashCode() và equals() một cách chính xác có thể phải chịu Differencing sử dụng thư viện này
  • vá và unpatch văn bản với các bản vá cho
  • phân tích các định dạng khác biệt thống nhất
  • tạo ra những khác biệt có thể đọc được của con người
+0

Cần cẩu được duy trì tích cực có vẻ là https://github.com/bkromhout/java-diff-utils – koppor

Các vấn đề liên quan