1 17 18 package com.finalist.util; 19 20 import com.finalist.jaggenerator.HtmlContentPopUp; 21 22 import java.io.*; 23 import java.util.*; 24 25 37 public class Diff { 38 private File file1; 39 private File file2; 40 private BufferedReader in1; 41 private BufferedReader in2; 42 private HashMap lineCounter = new HashMap(2); 43 44 private static final String REPORT_HEADER = 45 "<html><head><style type='text/css'>" + 46 "body, table { font-size: 9px; font-family: Verdana, Arial, Helvetica, sans-serif }" + 47 "font.file1 {color:#ff0000;}" + 48 "font.file1-code {color:#ff0000; font-family: 'courier new',monospace;}" + 49 "font.file2 {color:#0000ff;}" + 50 "font.file2-code {color:#0000ff; font-family: 'courier new',monospace;}" + 51 "</style></head><body>" + 52 "<table><tr><td width='30'><font class='file1'><</td><td>"; 53 54 61 public Diff(File file1, File file2) throws IOException { 62 this.file1 = file1; 63 this.file2 = file2; 64 if (!file1.exists()) { 65 throw new IOException("File " + file1 + " doesn't exist!"); 66 } 67 if (!file2.exists()) { 68 throw new IOException("File " + file2 + " doesn't exist!"); 69 } 70 in1 = new BufferedReader(new FileReader(file1)); 71 in2 = new BufferedReader(new FileReader(file2)); 72 lineCounter.put(in1, new Integer (1)); 73 lineCounter.put(in2, new Integer (1)); 74 } 75 76 84 public String performDiff() throws IOException { 85 List diffLines = getDiffLines(); 86 return createReport(diffLines); 87 } 88 89 95 public List getDiffLines() throws IOException { 96 ArrayList diffLines = new ArrayList(); 97 try { 98 DiffConflictLine line1 = nextLine(in1); 99 DiffConflictLine line2 = nextLine(in2); 100 while (!(line1.isEof() && line2.isEof())) { 101 if (line1.isEof()) { 102 diffLines.add(line2); 103 line2 = nextLine(in2); 104 continue; 105 } else if (line2.isEof()) { 106 diffLines.add(line1); 107 line1 = nextLine(in1); 108 continue; 109 } 110 if (line1.lineEquals(line2)) { 111 line1 = nextLine(in1); 113 line2 = nextLine(in2); 114 } else { 115 DiffConflictLine conflictLine = null; 116 if (containsLine(file2, line1.getLine(), line2.getLineNumber())) { 117 MatchResult betterMatch = bestMatch(line1.getLineNumber(), line2.getLineNumber()); 119 if (betterMatch != null) { 121 diffLines.add(line1); 122 while(line1.getLineNumber() < betterMatch.endFile1Sequence) { 123 line1 = nextLine(in1); 124 diffLines.add(line1); 126 } 127 line1 = nextLine(in1); 128 continue; 129 } else { 130 conflictLine = line2; 131 line2 = nextLine(in2); 132 } 133 } else { 134 conflictLine = line1; 136 line1 = nextLine(in1); 137 } 138 diffLines.add(conflictLine); 139 } 140 } 141 143 } finally { 144 if (in1 != null) try { in1.close(); } catch (IOException _) {} 145 if (in2 != null) try { in2.close(); } catch (IOException _) {} 146 } 147 return diffLines; 148 } 149 150 159 private MatchResult bestMatch(int count1, int count2) { 160 int matchDistance = count1; 161 int matchLength = 0; 162 BufferedReader in1 = null; 163 BufferedReader in2 = null; 164 try { 165 in1 = new BufferedReader(new FileReader(file1)); 166 in2 = new BufferedReader(new FileReader(file2)); 167 168 for (int i = 1; i < count1; i++) { 170 in1.readLine(); 171 } 172 for (int i = 1; i < count2; i++) { 173 in2.readLine(); 174 } 175 176 String s1 = in1.readLine(); 178 String s2 = in2.readLine(); 179 while (s1 != null) { 180 if (s1.trim().equals(s2.trim())) { 181 break; 182 } 183 s1 = in1.readLine(); 184 count1++; 185 } 186 if (s1 == null) { 187 return null; 189 } 190 matchDistance = count1 - matchDistance; 191 192 while (!(s1 == null || s2 == null) && 194 s1.trim().equals(s2.trim())) { 195 matchLength++; 196 s1 = in1.readLine(); 197 s2 = in2.readLine(); 198 } 199 } catch (FileNotFoundException e) { 200 } catch (IOException e) { 202 e.printStackTrace(); 203 } finally { 204 if (in1 != null) try { in1.close(); } catch (IOException _) {} 205 if (in2 != null) try { in2.close(); } catch (IOException _) {} 206 } 207 if (matchLength < matchDistance) { 208 return null; 209 } 210 211 return new MatchResult(matchLength, count1 - 1); 212 } 213 214 private boolean containsLine(File file, String line, int startPos) { 215 int lineCount = 0; 216 BufferedReader in = null; 217 try { 218 in = new BufferedReader(new FileReader(file)); 219 String s = in.readLine(); 220 lineCount++; 221 while (s != null) { 222 if (lineCount > startPos && s != null && line.trim().equals(s.trim())) { 223 return true; 224 } 225 s = in.readLine(); 226 lineCount++; 227 } 228 } catch (FileNotFoundException e) { 229 } catch (IOException e) { 231 e.printStackTrace(); 232 } finally { 233 if (in != null) try { in.close(); } catch (IOException _) {} 234 } 235 return false; 236 } 237 238 private DiffConflictLine nextLine(BufferedReader reader) throws IOException { 239 String line = ""; 240 int lineNumber = currentLineNumber(reader); 241 while (line != null && "".equals(line.trim())) { 242 line = reader.readLine(); 243 lineNumber++; 244 } 245 lineCounter.put(reader, new Integer (lineNumber)); 246 return line == null ? DiffConflictLine.EOF : new DiffConflictLine(reader == in1, lineNumber - 1, line); 247 } 248 249 private int currentLineNumber(BufferedReader reader) { 250 return ((Integer ) lineCounter.get(reader)).intValue(); 251 } 252 253 private String createReport(List diffLines) throws IOException { 254 if (diffLines.isEmpty()) { 255 return null; 256 } 257 StringBuffer report = new StringBuffer (REPORT_HEADER); 258 report.append(file1.getCanonicalPath()); 259 report.append("</font></td></tr><tr><td width='30'><font class='file2'>></td><td>"); 260 report.append(file2.getCanonicalPath()).append("</font></td></tr></table><br>"); 261 ArrayList temp = new ArrayList(); 262 for (int i = 0; i < diffLines.size(); i++) { 263 DiffConflictLine line = (DiffConflictLine) diffLines.get(i); 264 DiffConflictLine next = (i == diffLines.size() - 1) ? null : (DiffConflictLine) diffLines.get(i + 1); 265 if (line.precedes(next)) { 266 DiffConflictLine last = lastLine(temp); 267 if (last != null && !last.precedes(line)) { 268 reportLineGroup(report, temp); 269 } 270 temp.add(line); 271 continue; 272 } 273 if (temp.isEmpty()) { 274 reportSingleLine(report, line); 275 } else { 276 DiffConflictLine last = lastLine(temp); 277 if (last.precedes(line)) { 278 temp.add(line); 279 } else { 280 reportLineGroup(report, temp); 281 temp.add(line); 282 } 283 } 284 } 285 if (temp.size() > 1) { 286 reportLineGroup(report, temp); 287 } else if (temp.size() == 1) { 288 reportSingleLine(report, (DiffConflictLine) temp.get(0)); 289 } 290 291 report.append("</body></html>"); 292 return report.toString(); 293 } 294 295 private void reportSingleLine(StringBuffer report, DiffConflictLine line) { 296 report.append("<font class="); 297 report.append(line.isFirstFile() ? "'file1'" : "'file2'"); 298 report.append(">").append(line.getLineNumber()).append("</font><br>"); 299 report.append(line.toString()); 300 } 301 302 private void reportLineGroup(StringBuffer report, ArrayList temp) { 303 DiffConflictLine last = lastLine(temp); 304 DiffConflictLine first = (DiffConflictLine) temp.get(0); 305 report.append("<font class="); 306 report.append(first.isFirstFile() ? "'file1'" : "'file2'"); 307 report.append(">").append(first.getLineNumber()).append(',').append(last.getLineNumber()); 308 report.append("</font><br>"); 309 Iterator j = temp.iterator(); 310 while (j.hasNext()) { 311 DiffConflictLine groupedLine = (DiffConflictLine) j.next(); 312 report.append(groupedLine.toString()); 313 } 314 temp.clear(); 315 } 316 317 private DiffConflictLine lastLine(List group) { 318 return (group == null || group.isEmpty()) ? null : (DiffConflictLine) group.get(group.size() - 1); 319 } 320 321 326 public static void main(String [] args) { 327 try { 328 Diff diff = new Diff(new File(args[0]), new File(args[1])); 329 System.out.println(diff.performDiff()); 330 } catch (IOException e) { 331 e.printStackTrace(); 332 } 333 } 334 335 } 336 337 class MatchResult { 338 public MatchResult(int length, int endFile1Sequence) { 339 this.length = length; 340 this.endFile1Sequence = endFile1Sequence; 341 } 342 343 int endFile1Sequence; 344 int length; 345 346 public String toString() { 347 return "Match: end#1=" + endFile1Sequence + ", length=" + length; 348 } 349 350 } 351 | Popular Tags |