Comparing two files in java - java

I am trying to compare two .txt files (i.e their contents), but when I execute this code my application goes into an infinite loop. Why?
public int compareFile(String fILE_ONE2, String fILE_TWO2)throws Exception
{
File f1 = new File(fILE_ONE2); //OUTFILE
File f2 = new File(fILE_TWO2); //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;
else
flag=1;
}
reader1.close();
reader2.close();
return flag;
}

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.

Assuming text file inputs, an alternative implementation to the while loop:
while (true) // Continue while there are equal lines
{
line1 = reader1.readLine();
line2 = reader2.readLine();
if (line1 == null) // End of file 1
{
return (line2 == null ? 1 : 0); // Equal only if file 2 also ended
}
else if (line2 == null)
{
return 0; // File 2 ended before file 1, so not equal
}
else if (!line1.equalsIgnoreCase(line2)) // Non-null and different lines
{
return 0;
}
// Non-null and equal lines, continue until the input is exhausted
}
The first else if is not necessary, but it is included for clarity purposes. Otherwise, the above code could be simplified to:
while (true) // Continue while there are equal lines
{
line1 = reader1.readLine();
line2 = reader2.readLine();
if (line1 == null) // End of file 1
{
return (line2 == null ? 1 : 0); // Equal only if file 2 also ended
}
if (!line1.equalsIgnoreCase(line2)) // Different lines, or end of file 2
{
return 0;
}
}
The loop should be placed in a try/finally block, to assure that the readers are closed.

Above method by Jess will fail if file2 is same as file1 but has an extra line at the end.
This should work.
public boolean compareTwoFiles(String file1Path, String file2Path)
throws IOException {
File file1 = new File(file1Path);
File file2 = new File(file2Path);
BufferedReader br1 = new BufferedReader(new FileReader(file1));
BufferedReader br2 = new BufferedReader(new FileReader(file2));
String thisLine = null;
String thatLine = null;
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
while ((thisLine = br1.readLine()) != null) {
list1.add(thisLine);
}
while ((thatLine = br2.readLine()) != null) {
list2.add(thatLine);
}
br1.close();
br2.close();
return list1.equals(list2);
}

if you use java8, the code below to compare file contents
public boolean compareTwoFiles(String file1Path, String file2Path){
Path p1 = Paths.get(file1Path);
Path p1 = Paths.get(file1Path);
try{
List<String> listF1 = Files.readAllLines(p1);
List<String> listF2 = Files.readAllLines(p2);
return listF1.containsAll(listF2);
}catch(IOException ie) {
ie.getMessage();
}
}

Related

How to check if a string in a text file is correct

I have a text file and I need to check if it is correct. The file should be of the type:
XYab
XYab
XYab
Where X,Y,a,b can take only a certain range of value. For example b must be a value between 1 and 8. These values are defined by 4 enum (1 enum for X,1 enum for Y, etc..). The only thing that came to my mind is something like this:
BufferedReader br = new BufferedReader(new FileReader(FILENAME)
String s;
while ((s = br.readLine()) != null) {
if(s.charAt(0)==Enum.example.asChar())
}
But of course it checks only the first line of the file. Any advice on how I can check all the file's lines?
You could try something like this, (modify it according to yours enums)
#Test
public void findDates() {
File file = new File("pathToFile");
try{
Assert.assertTrue(validateFile(file));
}catch(Exception ex){
ex.printStackTrace();
}
}
private boolean validateFile(File file) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
// add yours enumns to one list
List<Enum> enums = new ArrayList<>();
enums.add(EnumX);
enums.add(EnumY);
enums.add(EnumA);
enums.add(EnumB);
while ((line = br.readLine()) != null) {
// process the line.
if(line.length() > 4){
return false;
}
//for each position check if the value is valid for the enum
for(int i = 0; i < 4; i++){
if(enums.get(i)).valueOf(line.charAt(i)) == null){
return false;
}
}
}
return true;
}
Don't forget about collision but if you have number or string you can use the regexp to do that.
On each Enum you have to do a function regexp like this. You can use an external Helper instead.
enum EnumX {
A,B,C,D, ...;
...
// you enum start to 0
public static String regexp(){
return "[0-" + EnumX.values().length +"]";
}
}
// it is working also if you have string in your file
enum EnumY{
A("toto"),B("titi"),C("tata"),D("loto");
public static String regexp(){
StringBuilder regexp = new StringBuilder("[");
for(EnumY value : EnumY.values()){
regexp.append(value).append(",");
}
regexp.replace(regexp.length()-1, regexp.length(), "]");
return regexp.toString();
}
}
public boolean isCorrect(File file){
// build the regexp
String regexp = EnumX.regexp() + EnumY.regexp() + EnumA.regexp() +EnumB.regexp();
// read the file
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
if (line.matches(regexp) == false){
// this line is not correct
return false;
}
}
return true;
}

How to append multiple text in text file

I want the results from 'name' and 'code' to be inserted into log.txt file, but if I run this program only the name results gets inserted into .txt file, I cannot see code results appending under name. If I do System.outprintln(name) & System.outprintln(code) I get results printed in console but its not being inserted in a file.Can someone tell me what am I doing wrong?
Scanner sc = new Scanner(file, "UTF-8");
BufferedReader br = new BufferedReader(new FileReader(file));
PrintWriter out = new PrintWriter(new FileWriter("log.txt", true));
while ((line = br.readLine()) != null) {
if (line.contains("text1")) {
String[] splits = line.split("=");
String name = splits[2];
for (int i = 0; i < name.length(); i++) {
out.println(name);
}
}
if (line.contains("text2")) {
String[] splits = line.split("=");
String code = splits[2];
for (int i = 0; i < code.length(); i++) {
out.println(code);
}
}
out.close()
}
File looks like:
Name=111111111
Code=333,5555
Category-Warranty
Name=2222222
Code=111,22
Category-Warranty
Have a look at this code. Does that work for you?
final String NAME = "name";
final String CODE = "code";
BufferedReader br = new BufferedReader(new FileReader(file));
PrintWriter out = new PrintWriter(new FileWriter("log.txt", true));
while ((line = br.readLine()) != null) {
String[] splits = line.split("=");
String key = splits[0];
String value = splits[1];
if (key.equals(NAME) || key.equals(CODE)) {
out.println(value);
}
}
out.close();
You have a couple of problems in your code:
you never actually assign the variables name and code.
you close() your PrintWriter inside the while-loop, that means you will have a problem if you read more than one line.
I don't see why this wouldn't work, without seeing more of what you are doing:
BufferedReader br = new BufferedReader(new FileReader(file));
PrintWriter out = new PrintWriter(new FileWriter("log.txt", true));
while ((line = br.readLine()) != null) {
if (line.contains("=")) {
if (line.contains("text1")) {
String[] splits = line.split("=");
if (splits.length >= 2) {
out.println(splits[1]);
}
}
if (line.contains("text2")) {
String[] splits = line.split("=");
if (splits.length >= 2) {
out.println(splits[1]);
}
}
}
}
out.flush();
out.close();
Make sure the second if condition is satisfied i.e. the line String contains "text2".

Take Strings from Text file and assign each line to value (2 at a time and insert into LinkedHashMap)

What I'm trying to do is, load a Text file, then take the values from each line and assign them to a variable in my program. Every two lines, I will insert them into a LinkedHashMap (As a pair)
The problem with a buffered reader is, all I can seem to do is, read one line at a time.
Here is my current code:
public static void receiver(String firstArg) {// Receives
// Input
// File
String cipherText;
String key;
String inFile = new File(firstArg).getAbsolutePath();
Path file = new File(inFile).toPath();
// File in = new File(inFile);
try (InputStream in = Files.newInputStream(file);
BufferedReader reader = new BufferedReader(
new InputStreamReader(in))) {
String line = null;
while ((line = reader.readLine()) != null) {
// System.out.println(line);
String[] arrayLine = line.split("\n"); // here you are
// splitting
// with whitespace
cipherText = arrayLine[0];
// key = arrayLine[1];
System.out.println(arrayLine[0] + " " + arrayLine[1]);
cipherKeyPairs.put(arrayLine[0], arrayLine[1]);
}
} catch (IOException x) {
System.err.println(x);
}
The problem is, it can't find the arrayLine[1] (for obvious reasons). I need it to read two lines at a time without the array going out of bounds.
Any idea how to do this, so that I can store them into my LinkedHashMap, two lines at a time as separate values.
You can overcome this issue by inserting in the List every 2 lines reading.
A description for this code is that: "Bold is the true case"
Read the first line (count is 0)
If (secondLine is false) ==> Save the line to CipherText variable, make secondLine = true
Else If (secondLine is true) ==> Add to list (CipherText, line), make secondLine = false
Read the second line (count is 1)
If (secondLine is false) ==> Save the line to CipherText variable, make secondLine = true
Else If (secondLine is true) ==> Add to list (CipherText, line), make secondLine = false
String cipherText;
boolean secondLine = false;
String inFile = new File(firstArg).getAbsolutePath();
Path file = new File(inFile).toPath();
try {
InputStream in = Files.newInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
String line = null;
while ((line = reader.readLine()) != null) {
if (!secondLine) //first line reading
{
cipherText = line;
secondLine = true;
}
else if (secondLine) //second line reading
{
cipherKeyPairs.put(cipherText, line);
secondLine = false;
}
}
} catch (IOException x) {
System.err.println(x);
}
See if this works for you. I just edited your code. it might not be the best answer.
public static void receiver(String firstArg) {// Receives
// Input
// File
String cipherText;
String key;
String inFile = new File(firstArg).getAbsolutePath();
Path file = new File(inFile).toPath();
// File in = new File(inFile);
try (InputStream in = Files.newInputStream(file);
BufferedReader reader = new BufferedReader(
new InputStreamReader(in))) {
String line = null;
List<String> lines = new ArrayList();
while ((line = reader.readLine()) != null) {
lines.add(line);//trim line first though and check for empty string
}
for(int i=1;i<lines.size();i++){
cipherText = arrayLine[i];
// key = arrayLine[1];
System.out.println(arrayLine[i] + " " + arrayLine[i-1]);
cipherKeyPairs.put(arrayLine[i-1], arrayLine[i]);
}
} catch (IOException x) {
System.err.println(x);
}
}

Java File cannot be deleted nor renamed

See my code below:
I can write a key and a string in one line of a file. If the key already exists I want to overwrite it by creating a new file and fill it with the content of my source file. In the end I am going to delete the old file and rename my temporary file. But it does not work. As you can see I print booleans for deleting and renameTo methods. Both are returned as "false".
I read in some other Threads that I have to close all Readers and Writers that are in contact with my file in order to be able to rename or delete it.
You see my fault?
(Note that some comments are written in german)
public static boolean dini_Set(String filepath, String key, String value) throws IOException
{
if(key.length() <= 0 || value.length() <= 0) return false;
String pfilepath = rootdirectory.concat(filepath);
File pfile = new File(pfilepath);
//dini_Remove(filepath.concat(".part"));
if(dini_Exists(filepath) == false) return false;
// Checkt ob der Key schon existiert
FileReader fr = new FileReader(pfilepath);
BufferedReader br = new BufferedReader(fr);
String ausw;
boolean foundkeybool = false;
while((ausw = br.readLine()) != null)
{
String foundkey = ausw.substring(0,ausw.indexOf("="));
//System.out.println(foundkey);
if(foundkey.equals(key))
{
foundkeybool = true;
System.out.println(foundkeybool);
// Key exists and content has to be overwritten
String newline = key.concat("=").concat(value);
String tmpdir = rootdirectory.concat("tmp.tmp");
File tmp = new File(tmpdir);
tmp.createNewFile();
String currentLine;
FileWriter fw = new FileWriter(tmpdir);
BufferedWriter bw = new BufferedWriter(fw);
br.close();
fr.close();
fr = new FileReader(pfilepath);
br = new BufferedReader(fr);
while((currentLine = br.readLine()) != null)
{
// trim newline when comparing with lineToRemove
String trimmedLine = currentLine.trim();
System.out.println(trimmedLine);
if(trimmedLine.equals(ausw))
{
System.out.println("Austauschen: "+newline);
bw.write(newline);
}
else
{
bw.write(currentLine);
System.out.println("Lassen: "+currentLine);
}
bw.newLine();
}
br.close();
fr.close();
bw.close();
fw.close();
tmp.setWritable(true);
pfile.setWritable(true);
// boolean removed = dini_Remove(filepath);
boolean removed = pfile.delete();
System.out.println("Datei wurde gelöscht: "+removed);
boolean renamed = tmp.renameTo(pfile);
System.out.println("Datei umbenannt: "+renamed);
break;
}
}
// if key does now exists we can create a new one
if(foundkeybool == false)
{
FileWriter fw = new FileWriter(pfilepath,true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(key.concat("=").concat(value));
bw.newLine();
bw.close();
}
return true;
}
This may not fix your problem, but it will get you closer.
You MUST ensure that any resource that you open is closed properly. Currently in your code, if, for some reason, an exception is thrown, none of your resources will be closed.
Even if you're not interested in dealing with the exception within the method, you should still wrap the file access code within a try-finally block
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(pfilepath);
br = new BufferedReader(fr);
//...//
} finally {
try {
br.close();
} catch (Exception exp) {
}
try {
fr.close();
} catch (Exception exp) {
}
}
You may find that you only need to close the BufferedReader and it should be calling close on it's child Reader, but I'm paranoid about ensuring that everything is clean
If you are using Java 7, you may wish to take a look at The try-with-resources Statement
Updated
I'm not sure your code makes sense. Basically, what you should be doing, is reading the entire source file and writing it the temp location (as you don't know in advance if the key needs to be updated, and you would probably need to read the source file anyway to find out).
Once this has being completed, if you made changes to the temp file, delete the source file and rename the temp file into it's place.
You code seems mighty inefficient to me...
Okai, I want to give you a brief update about the code.
I changed it this way and for now it is working as it should.
Do you have some more things I can change to optimize the code?
public static boolean dini_Set(String filepath, String key, String value) throws IOException
{
if(key.length() <= 0 || value.length() <= 0) return false;
String pfilepath = rootdirectory.concat(filepath);
File pfile = new File(pfilepath);
//dini_Remove(filepath.concat(".part"));
if(dini_Exists(filepath) == false) return false;
// Checkt ob der Key schon existiert
boolean foundkeybool = false;
File tmp = null;
try(BufferedReader br = new BufferedReader(new FileReader(pfilepath)))
{
String ausw;
while((ausw = br.readLine()) != null)
{
String foundkey = ausw.substring(0,ausw.indexOf("="));
System.out.println(foundkey);
if(foundkey.equals(key))
{
foundkeybool = true;
System.out.println(foundkeybool);
//Key exists and content has to be overwritten
String newline = key.concat("=").concat(value);
String tmpdir = rootdirectory.concat("tmp.tmp");
tmp = new File(tmpdir);
tmp.createNewFile();
String currentLine;
try(BufferedWriter bw = new BufferedWriter(new FileWriter(tmpdir)))
{
try(BufferedReader br2 = new BufferedReader(new FileReader(pfilepath)))
{
while((currentLine = br2.readLine()) != null)
{
//trim newline when comparing with lineToRemove
String trimmedLine = currentLine.trim();
System.out.println(trimmedLine);
if(trimmedLine.equals(ausw))
{
System.out.println("Austauschen: "+newline);
bw.write(newline);
}
else
{
bw.write(currentLine);
System.out.println("Lassen: "+currentLine);
}
bw.newLine();
}
}
}
break;
}
}
}
if(foundkeybool == true)
{
tmp.setWritable(true);
pfile.setWritable(true);
//boolean removed = dini_Remove(filepath);
boolean removed = pfile.delete();
System.out.println("Datei wurde gelöscht: "+removed);
boolean renamed = tmp.renameTo(pfile);
System.out.println("Datei umbenannt: "+renamed);
}
else //(foundkeybool == false) if key does now exists we can create a new one
{
try(BufferedWriter bw = new BufferedWriter(new FileWriter(pfilepath,true)))
{
bw.write(key.concat("=").concat(value));
bw.newLine();
bw.close();
}
}
return true;
}

readLine() null return

I have the following code:
public static void main(String[] args) throws Exception {
String s = "";
StringBuilder sb = new StringBuilder();
File file = new File("C:\\New\\r.txt");
BufferedReader in = new BufferedReader(new FileReader(file));
while(in.readLine() != null) {
sb.append(in.readLine());
}
System.out.println(sb);
s = sb.toString();
byte[] b = s.getBytes();
for(int i = 0; i < b.length; i++) {
if(b[i] == 1){ b[i]=0; }
if(b[i] == 0){ b[i]=1; }
}
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
dos.write(b);
in.close();
fos.close();
dos.close();
}
I get a return of null when I run this program. Maybe I must elevate the program? Help would be appreciated.
Change:
while(in.readLine()!=null)
to:
while((s = in.readLine())!=null)
and then:
sb.append(s);
When you call in your code to in.readLine() twice - you're reading two lines but printing only the second in each iteration.
You're throwing away every odd line:
while(in.readLine()!=null)
{
sb.append(in.readLine());
}
If r.txt only contains one line, you will get the string "null" in the StringBuffer, because the first line of StringBuffer.append does this:
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
....
}
If there are two lines, you will get the first line with "null" at the end of the line.
The following will append all lines from the file to the StringBuffer:
String line = null;
while((line = in.readLine()) != null)
{
sb.append(line);
}
your code
while(in.readLine() != null) {
sb.append(in.readLine());
}
change with it
while ((s = in.readLine()) != null)
{
sb.append(s);
}

Categories

Resources