001 package calhoun.util;
002
003 import java.io.BufferedReader;
004 import java.io.File;
005 import java.io.FileInputStream;
006 import java.io.IOException;
007 import java.io.InputStreamReader;
008 import java.io.PrintWriter;
009 import java.io.Reader;
010 import java.io.StringWriter;
011 import java.util.ArrayList;
012
013 import bmsi.util.Diff;
014 import bmsi.util.DiffPrint;
015
016 /**
017 * Computes the 'diff' difference between two files. By default, whitespace in the files is ignored.
018 */
019 public class FileDiff
020 {
021 private String[] firstLines;
022 private String[] secondLines;
023
024 private boolean closeReaders;
025 private Reader firstLinesReader;
026 private Reader secondLinesReader;
027 private boolean ignoreWhitespace = true;
028 private String commentLineIndicator;
029 private Diff.change change = null;
030
031 public static boolean filesMatch(String first, String second) throws IOException {
032 return !new FileDiff(first, second).execute();
033 }
034
035 /** Constructor takes 2 file names - opens the files using UTF-8 encoding.
036 */
037 public FileDiff(String first, String second) throws IOException
038 {
039 this(new InputStreamReader( new FileInputStream(first), "UTF-8" ), new InputStreamReader( new FileInputStream(second),"UTF-8"), true );
040 }
041
042 /** Constructor takes 2 Files - opens the files using UTF-8 encoding.
043 */
044 public FileDiff(File first, File second) throws IOException
045 {
046 this(new InputStreamReader( new FileInputStream(first), "UTF-8" ), new InputStreamReader( new FileInputStream(second),"UTF-8"), true );
047 }
048
049 public FileDiff(Reader first, Reader second)
050 {
051 this( first,second, false );
052 }
053
054 public FileDiff(Reader first, Reader second, boolean closeReaders )
055 {
056 this.firstLinesReader = first;
057 this.secondLinesReader = second;
058 this.closeReaders = closeReaders;
059 }
060
061 /**
062 * Sets whether to ignore whitespace. By default, whitespace is ignored.
063 * @see #getIgnoreWhitespace
064 */
065 public void setIgnoreWhitespace(boolean b)
066 {
067 ignoreWhitespace = b;
068 }
069
070 /**
071 * @see #setIgnoreWhitespace
072 */
073 public boolean getIgnoreWhitespace()
074 {
075 return ignoreWhitespace;
076 }
077
078 /**
079 * Sets the comment line indicator string. If set, lines beginning with this string are not used in the diff comparison.
080 * @see #getCommentLineIndicator
081 */
082 public void setCommentLineIndicator(String commentLineIndicator)
083 {
084 this.commentLineIndicator = commentLineIndicator;
085 }
086
087 /**
088 * Gets the comment line indicator string.
089 * @see #setCommentLineIndicator
090 */
091 public String getCommentLineIndicator()
092 {
093 return commentLineIndicator;
094 }
095
096 /**
097 * @return whether the two files were different.
098 * @see #toString
099 */
100 public boolean execute() throws IOException
101 {
102 firstLines = readLines(firstLinesReader);
103 secondLines = readLines(secondLinesReader);
104 if ( closeReaders )
105 {
106 firstLinesReader.close();
107 secondLinesReader.close();
108 }
109 Diff diff = new Diff(firstLines, secondLines);
110 change = diff.diff_2(false);
111 return change != null;
112 }
113
114 /**
115 * @return a diff-style listing of the differences between the 2 files. If the files were identical,
116 * returns the empty string ('').
117 */
118 @Override
119 public String toString()
120 {
121 if ( change != null )
122 {
123 DiffPrint.NormalPrint np = new DiffPrint.NormalPrint(firstLines, secondLines);
124 StringWriter str = new StringWriter();
125 PrintWriter writer = new PrintWriter(str);
126 np.setWriter(writer);
127 np.print_script(change);
128 writer.close();
129 return str.toString();
130 }
131 else
132 {
133 return "";
134 }
135 }
136
137 private String[] readLines(Reader r) throws IOException
138 {
139 BufferedReader reader = new BufferedReader(r);
140 ArrayList lines = new ArrayList();
141 String line;
142 while ( ( line = reader.readLine() ) != null )
143 {
144 if ( ignoreWhitespace )
145 line = line.trim();
146
147 if ( (!ignoreWhitespace || !"".equals(line)) &&
148 (commentLineIndicator == null || !line.startsWith(commentLineIndicator)) )
149 {
150 lines.add(line);
151 }
152 }
153 String[] result = new String[lines.size()];
154 return (String[])lines.toArray(result);
155 }
156 }