(See the next and second iteration here.)
I have this toy implementation of the diff
utility in Java:
com.github.coderodde.diff.Diff.java
package com.github.coderodde.diff;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Diff {
private static final String NL = "\n";
public static void main(String[] args) {
if (args.length != 2) {
return;
}
File oldSourceFile = new File(args[0]);
File newSourceFile = new File(args[1]);
BufferedReader oldSourceBufferedReader = null;
BufferedReader newSourceBufferedReader = null;
try {
oldSourceBufferedReader =
new BufferedReader(new FileReader(oldSourceFile));
newSourceBufferedReader =
new BufferedReader(new FileReader(newSourceFile));
} catch (IOException ex) {
System.err.println("I/O failed: " + ex.getMessage());
System.exit(1);
}
List<String> oldSourceLines = new ArrayList<>();
List<String> newSourceLines = new ArrayList<>();
String oldSourceLine;
String newSourceLine;
try {
while ((oldSourceLine = oldSourceBufferedReader.readLine()) != null) {
oldSourceLines.add(oldSourceLine);
}
while ((newSourceLine = newSourceBufferedReader.readLine()) != null) {
newSourceLines.add(newSourceLine);
}
} catch (IOException ex) {
System.err.println("I/O failed: " + ex.getMessage());
System.exit(1);
}
System.out.println(computeDiff(oldSourceLines, newSourceLines));
}
private static String computeDiff(List<String> oldSourceLines,
List<String> newSourceLines) {
int[][] matrix = computeLongestCommonSubsequenceData(oldSourceLines,
newSourceLines);
return printDiff(matrix, oldSourceLines, newSourceLines);
}
private static int[][] computeLongestCommonSubsequenceData(
List<String> oldSourceLines,
List<String> newSourceLines) {
int[][] matrix = new int[oldSourceLines.size() + 1]
[newSourceLines.size() + 1];
for (int i = 1; i <= oldSourceLines.size(); ++i) {
for (int j = 1; j <= newSourceLines.size(); ++j) {
if (oldSourceLines.get(i - 1)
.equals(newSourceLines.get(j - 1))) {
matrix[i][j] = matrix[i - 1][j - 1] + 1;
} else {
matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
}
}
}
return matrix;
}
private static String printDiff(int[][] matrix,
List<String> oldSourceLines,
List<String> newSourceLines) {
StringBuilder stringBuilder = new StringBuilder();
printDiff(stringBuilder,
matrix,
oldSourceLines,
newSourceLines,
oldSourceLines.size() - 1,
newSourceLines.size() - 1);
return stringBuilder.toString();
}
private static void printDiff(StringBuilder stringBuilder,
int[][] matrix,
List<String> oldSourceLines,
List<String> newSourceLines,
int i,
int j) {
if (i >= 0
&& j >= 0
&& oldSourceLines.get(i).equals(newSourceLines.get(j))) {
printDiff(stringBuilder,
matrix,
oldSourceLines,
newSourceLines,
i - 1,
j - 1);
stringBuilder.append(" ").append(oldSourceLines.get(i)).append(NL);
} else if (j > 0 && (i == 0 || matrix[i][j - 1] >= matrix[i - 1][j])) {
printDiff(stringBuilder,
matrix,
oldSourceLines,
newSourceLines,
i,
j - 1);
stringBuilder.append("+ ").append(newSourceLines.get(j)).append(NL);
} else if (i > 0 && (j == 0 || matrix[i][j - 1] < matrix[i - 1][j])) {
printDiff(stringBuilder,
matrix,
oldSourceLines,
newSourceLines,
i - 1,
j);
stringBuilder.append("- ").append(oldSourceLines.get(i)).append(NL);
}
}
}
Critique request
What do you think? Would it be better to hide the diff process into a class, for instance?
diff("a\nb\nd\ne\ng"), List.of("a\nc\nd\nf\ng"))
returns" a\n- b\n+ c\n- d\n- e\n+ d\n+ f\n g"
instead of" a\n- b\n+ c\n d\n- e\n+ f\n g"
. Is that correct? \$\endgroup\$