Your code should be
Scanner input1 = new Scanner(new File(firstName));//read first file
Scanner input2 = new Scanner(new File(secondName));//read second file
while(input1.hasNextLine() && input2.hasNextLine()){
first = input1.nextLine();
second = input2.nextLine();
if(!first.equals(second)){
System.out.println("Differences found: "+"\n"+first+'\n'+second);
}
}
// optionally handle any remaining lines if the line count differs
Previously you only compared one time, the very last line. But you need to compare after each line you read.
Answer from luk2302 on Stack OverflowVideos
HashMap solution
I thought about it and the HashMap solution is instant. I went ahead and coded up an example of it here.
It runs in 0ms while the arrayLists ran in 16ms for the same dataset
public static void main(String[] args) throws Exception {
BufferedReader br1 = null;
BufferedReader br2 = null;
BufferedWriter bw3 = null;
String sCurrentLine;
int linelength;
HashMap<String, Integer> expectedrecords = new HashMap<String, Integer>();
HashMap<String, Integer> actualrecords = new HashMap<String, Integer>();
br1 = new BufferedReader(new FileReader("expected.txt"));
br2 = new BufferedReader(new FileReader("actual.txt"));
while ((sCurrentLine = br1.readLine()) != null) {
if (expectedrecords.containsKey(sCurrentLine)) {
expectedrecords.put(sCurrentLine, expectedrecords.get(sCurrentLine) + 1);
} else {
expectedrecords.put(sCurrentLine, 1);
}
}
while ((sCurrentLine = br2.readLine()) != null) {
if (expectedrecords.containsKey(sCurrentLine)) {
int expectedCount = expectedrecords.get(sCurrentLine) - 1;
if (expectedCount == 0) {
expectedrecords.remove(sCurrentLine);
} else {
expectedrecords.put(sCurrentLine, expectedCount);
}
} else {
if (actualrecords.containsKey(sCurrentLine)) {
actualrecords.put(sCurrentLine, actualrecords.get(sCurrentLine) + 1);
} else {
actualrecords.put(sCurrentLine, 1);
}
}
}
// expected is left with all records not present in actual
// actual is left with all records not present in expected
bw3 = new BufferedWriter(new FileWriter(new File("c.txt")));
bw3.write("Records which are not present in actual\n");
for (String key : expectedrecords.keySet()) {
for (int i = 0; i < expectedrecords.get(key); i++) {
bw3.write(key);
bw3.newLine();
}
}
bw3.write("Records which are in actual but not present in expected\n");
for (String key : actualrecords.keySet()) {
for (int i = 0; i < actualrecords.get(key); i++) {
bw3.write(key);
bw3.newLine();
}
}
bw3.flush();
bw3.close();
}
ex:
expected.txt
one
two
four
five
seven
eight
actual.txt
one
two
three
five
six
c.txt
Records which are not present in actual
four
seven
eight
Records which are in actual but not present in expected
three
six
ex 2:
expected.txt
one
two
four
five
seven
eight
duplicate
duplicate
duplicate
actual.txt
one
duplicate
two
three
five
six
c.txt
Records which are not present in actual
four
seven
eight
duplicate
duplicate
Records which are in actual but not present in expected
three
six
In Java 8 you can use Collection.removeIf(Predicate<T>)
list1.removeIf(line -> list2.contains(line));
list2.removeIf(line -> list1.contains(line));
list1 will then contain everything that is NOT in list2 and list2 will contain everything, that is NOT in list1.
I converted your code into a main program. There is no infinite loop in this code.
I am assuming you are comparing 2 text files of a small-ish size.
import java.io.*;
public class Diff {
public static void main(String[] args) throws FileNotFoundException, IOException {
File f1 = new File(args[0]);// OUTFILE
File f2 = new File(args[1]);// INPUT
FileReader fR1 = new FileReader(f1);
FileReader fR2 = new FileReader(f2);
BufferedReader reader1 = new BufferedReader(fR1);
BufferedReader reader2 = new BufferedReader(fR2);
String line1 = null;
String line2 = null;
int flag = 1;
while ((flag == 1) && ((line1 = reader1.readLine()) != null)
&& ((line2 = reader2.readLine()) != null)) {
if (!line1.equalsIgnoreCase(line2))
flag = 0;
}
reader1.close();
reader2.close();
System.out.println("Flag " + flag);
}
}
I ran it on 2 small different text files. This is the output.
javac Diff.java && java Diff a.txt b.txt
Flag 0
If you think you have an infinite loop, the issue might be elsewhere.
The code looks good, no infinite loops. You can remove irrespective check in the code and can update the code as below:
int flag=1;
while (((line1 = reader1.readLine()) != null)&&((line2 = reader2.readLine()) != null))
{
if (!line1.equalsIgnoreCase(line2))
{
flag=0;
break;
}
}
As the return type of the method is integer than it will return 0 if different and 1 if equal.
Exactly what FileUtils.contentEquals method of Apache commons IO does and api is here.
Try something like:
File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
boolean isTwoEqual = FileUtils.contentEquals(file1, file2);
It does the following checks before actually doing the comparison:
- existence of both the files
- Both file's that are passed are to be of file type and not directory.
- length in bytes should be the same.
- Both are different files and not one and the same.
- Then compare the contents.
If you don't want to use any external libraries, then simply read the files into byte arrays and compare them (won't work pre Java-7):
byte[] f1 = Files.readAllBytes(file1);
byte[] f2 = Files.readAllBytes(file2);
by using Arrays.equals.
If the files are large, then instead of reading the entire files into arrays, you should use BufferedInputStream and read the files chunk-by-chunk as explained here.
The simplest way is to read the contents into two strings e.g.
FileInputStream fin = new FileInputStream(args[i]);
BufferedReader myInput = new BufferedReader(new InputStreamReader(fin));
StringBuilder sb = new StringBuilder();
while ((thisLine = myInput.readLine()) != null) {
sb.append(thisLine);
}
, and perform a .equals() on these. Do you require more complex differencing capabilities ?
import java.io.*;
public class Testing {
public static void main(String[] args) throws java.io.IOException {
BufferedReader bfr2 = new BufferedReader(new InputStreamReader(
System.in));
String s1 = "";
String s2 = "", s3 = "", s4 = "";
String y = "", z = "";
File file1 = new File("args[0]");
File file2 = new File("args[1]");
BufferedReader bfr = new BufferedReader(new FileReader(file1));
BufferedReader bfr1 = new BufferedReader(new FileReader(file2));
while ((z = bfr1.readLine()) != null)
s3 += z;
while ((y = bfr.readLine()) != null)
s1 += y;
System.out.println();
System.out.println(s3);
if (s3.equals(s1)) {
System.out.println("Content of both files are same");
} else {
System.out.println("Content of both files are not same");
}
}
}
File f1 = new File("FILE_ONE");
File f2 = new File("FILE_TWO");
Try removing the quotes here. You declared FILE_ONE and FILE_TWO as variables earlier in your program, but you aren't calling them. Instead, you've directly called a string "FILE_ONE," which will of course not be found. So replace it with the parameters you passed to CompareFile...
File f1 = new File(fILE_ONE2);
File f2 = new File(fILE_TWO2);
And tell us if that takes care of it.
You have to remove the quotes from:
File f1 = new File("FILE_ONE");
and
File f2 = new File("FILE_TWO");
Also, make sure in the files' path "/Users/abextra/myText1.txt", "Users" is really supposed to be uppercase.
On many systems, /users/ is lowercase.