2008-11-26 7 views
17

¿Existen bibliotecas para Java que acepten dos cadenas y devuelvan una cadena con salida formateada según el comando * nix diff?Generar salida de formato formateado en Java

p. Ej. alimentar en

test 1,2,3,4 
test 5,6,7,8 
test 9,10,11,12 
test 13,14,15,16 

y

test 1,2,3,4 
test 5,6,7,8 
test 9,10,11,12,13 
test 13,14,15,16 

como entrada, y le daría

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 

Exactamente lo mismo que si hubiera pasado los archivos a diff -y expected actual

encontré this question, y da algunos buenos consejos sobre bibliotecas generales para darte p salida rogrammática, pero estoy queriendo los resultados de cadena recta.

podría llamar diff directamente como una llamada al sistema, pero esta aplicación particular, va a correr en Unix y Windows y no puedo estar seguro de que el medio ambiente tendrá realmente diff disponible.

Respuesta

6

Terminé de hacer mi propio trabajo. No estoy seguro si es la mejor implementación, y es feo como el infierno, pero pasa frente a la entrada de prueba.

Utiliza java-diff a hacer el trabajo pesado diff (cualquier Commons StrBuilder apache y StringUtils en lugar de acciones de 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

¿Se puede publicar maxLength() amd value of NONE? Gracias por ahorrarme toneladas de desarrollo – Bostone

+0

¿Encontró la biblioteca java-diff-utils deficiente? Solo quiero saber (disculpe el juego de palabras). –

0

Busybox tiene una implementación de diff que es muy delgada, no debería ser difícil de convertir a java, pero tendría que agregar la funcionalidad de dos columnas.

0

http://c2.com/cgi/wiki?DiffAlgorithm Encontré esto en Google y ofrece algunos buenos antecedentes y enlaces. Si le importa el algoritmo más allá de simplemente hacer el proyecto, un libro sobre algoritmo básico que cubre la Programación Dinámica o un libro sobre él. El conocimiento del algoritmo siempre es bueno :)

+0

Obtener implementaciones de trabajo en Java es la parte más fácil: están ahí. El bit duro en realidad estaba formateando la salida en un formato que se requiere. – madlep

14

java-diff-utils

La biblioteca Diffutils para calcular diferenciaciones, la aplicación de parches , generationg vista una al lado de la otra en Java

La biblioteca Diff Utils es una OpenSource biblioteca para realizar la comparación operaciones entre los textos: Computación diferenciaciones, la aplicación de parches, generando diffs unificados o analizar ellos, generar salida del diff para facilitar la futura mostrar (como vistas de lado a lado) y así sucesivamente.

La razón principal para construir esta biblioteca fue la falta de bibliotecas y fáciles de usar con todo lo habitual que necesita mientras trabajar con archivos diff. Originalmente, se inspiró en la biblioteca JRCS y es buen diseño del módulo diff.

Características principales

  • calculando la diferencia entre dos textos.
  • capaz de entregar más que simples ascci. Las matrices o una lista de cualquier tipo que implementa hashCode() y equals() correctamente puede estar sujeto a diferenciación utilizando esta biblioteca
  • parche y despachear el texto con el parche dado
  • analizar el formato diff unificado
  • produciendo diferencias legibles para el ser humano
+0

La horquilla mantenida activamente parece ser https://github.com/bkromhout/java-diff-utils – koppor