Iterative function issue - java

Im having some issues with a function that I have written. The function basically takes a file and a string into the method as parameters and searches the file for that string and replaces it with "".
public void removeReminder(File a, String search) throws IOException {
File tempFile = File.createTempFile("file", ".txt", a.getParentFile());
BufferedReader br = new BufferedReader(new FileReader(a));
PrintWriter pw = new PrintWriter(new FileWriter(tempFile));
for (String line; (line = br.readLine()) != null;) {
line = line.replace(search, "");
pw.println(line);
}
br.close();
pw.close();
a.delete();
tempFile.renameTo(a);
}
I then have 3 text files that I need to run this method for. Below is the code where i run the function.
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// TODO
try {
String names = reminderNameField.getText();
String date = reminderDate.getText();
String details = reminderDetailsField.getText();
File fileName = new File("reminderNames.txt");
File fileDate = new File("reminderDate.txt");
File fileDetails = new File("reminderDetails.txt");
removeReminder(fileName, names);
removeReminder(fileDate, date);
removeReminder(fileDetails, details);
} catch (IOException e){
e.printStackTrace();
}
I dont know why this isnt working. It works for the first iteration (e.g removeReminder(fileName, names);) But it doesnt work for the other ones, it seems to just ignore them :s can anyone tell me why this is?

I always flush printwriter. Try flushing PrintWriter before calling close().
pw.flush();

Related

Writing to File duplicating data the second time JAVA

I'm creating a program to remove doctors from an arrayList that is utilising a queue. This works the first time perfectly however, the second time it's duplicating the data inside the text file. How can I solve this?
/**
*
* #throws Exception
*/
public void writeArrayListToFile() throws Exception {
String path = "src/assignment1com327ccab/DoctorRecordsFile.txt";
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(path));
BufferedWriter br = new BufferedWriter(os);
PrintWriter out = new PrintWriter(br);
DoctorNode temp; //create a temporary doctorNode object
temp = end; //temp is equal to the end of the queue
//try this while temp is not equal to null (queue is not empty)
StringBuilder doctor = new StringBuilder();
while (temp != null) {
{
doctor.append(temp.toStringFile());
doctor.append("\n");
//temp is equal to temp.getNext doctor to get the next doctor to count
temp = temp.getNext();
}
}
System.out.println("Finished list");
System.out.println("Doctors is : " + doctor.toString());
out.println(doctor.toString());
System.out.println("Done");
br.newLine();
br.close();
}
This is not 100% solution but I think it will give you the right directions. I don't want to do 100% work for you :)
In my comment I said
Read file content
Store it in variable
Remove file
Remove doctors from variable
Write variables to new file
So, to read file content we would use something file this (if it's txt file):
public static String read(File file) throws FileNotFoundException {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file.getAbsoluteFile()));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
line = br.readLine();
if (line != null) sb.append(System.lineSeparator());
}
String everything = sb.toString();
return everything;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
This method returns String as file content. We can store it in a variable like this:
String fileContent = MyClass.read(new File("path to file"));
Next step would be to remove our file. Since we have it in memory, and we don't want duplicate values...
file.delete();
Now we should remove our doctors from fileContent. It's basic String operations. I would recommend using method replace() or replaceAll().
And after the String manipulation, just write fileContent to our file again.
File file = new File("the same path");
file.createNewFile();
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file, true), "UTF-8"));
out.write(fileContent);
out.flush();
out.close();

Java code optimization, replacing all chars in a file

I have tried doing it like this:
import java.io.*;
public class ConvertChar {
public static void main(String args[]) {
Long now = System.nanoTime();
String nomCompletFichier = "C:\\Users\\aahamed\\Desktop\\test\\test.xml";
Convert(nomCompletFichier);
Long inter = System.nanoTime() - now;
System.out.println(inter);
}
public static void Convert(String nomCompletFichier) {
FileWriter writer = null;
BufferedReader reader = null;
try {
File file = new File(nomCompletFichier);
reader = new BufferedReader(new FileReader(file));
String oldtext = "";
while (reader.ready()) {
oldtext += reader.readLine() + "\n";
}
reader.close();
// replace a word in a file
// String newtext = oldtext.replaceAll("drink", "Love");
// To replace a line in a file
String newtext = oldtext.replaceAll("&(?!amp;)", "&");
writer = new FileWriter(file);
writer.write(newtext);
writer.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
However the code above takes more time to execute than creating two different files:
import java.io.*;
public class ConvertChar {
public static void main(String args[]) {
Long now = System.nanoTime();
String nomCompletFichier = "C:\\Users\\aahamed\\Desktop\\test\\test.xml";
Convert(nomCompletFichier);
Long inter = System.nanoTime() - now;
System.out.println(inter);
}
private static void Convert(String nomCompletFichier) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
File file = new File(nomCompletFichier);
File tempFile = File.createTempFile("buffer", ".tmp");
bw = new BufferedWriter(new FileWriter(tempFile, true));
br = new BufferedReader(new FileReader(file));
while (br.ready()) {
bw.write(br.readLine().replaceAll("&(?!amp;)", "&") + "\n");
}
bw.close();
br.close();
file.delete();
tempFile.renameTo(file);
} catch (IOException e) {
// writeLog("Erreur lors de la conversion des caractères : " + e.getMessage(), 0);
} finally {
try {
bw.close();
} catch (Exception ignore) {
}
try {
br.close();
} catch (Exception ignore) {
}
}
}
}
Is there any way to do the 2nd code without creating a temp file and reducing the execution time? I am doing a code optimization.
The main reason why your first program is slow is probably that it's building up the string oldtext incrementally. The problem with that is that each time you add another line to it it may need to make a copy of it. Since each copy takes time roughly proportional to the length of the string being copied, your execution time will scale like the square of the size of your input file.
You can check whether this is your problem by trying with files of different lengths and seeing how the runtime depends on the file size.
If so, one easy way to get around the problem is Java's StringBuilder class which is intended for exactly this task: building up a large string incrementally.
The main culprit in your first example is that you're building oldtext inefficiently using String concatenations, as explained here. This allocates a new string for every concatenation. Java provides you StringBuilder for building strings:
StringBuilder builder = new StringBuilder;
while(reader.ready()){
builder.append(reader.readLine());
builder.append("\n");
}
String oldtext = builder.toString();
You can also do the replacement when you're building your text in StringBuilder. Another problem with your code is that you shouldn't use ready() to check if there is some content left in the file - check the result of readLine(). Finally, closing the stream should be in a finally or try-with-resources block. The result could look like this:
StringBuilder builder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = reader.readLine();
while (line != null) {
builder.append(line.replaceAll("&(?!amp;)", "&"));
builder.append('\n');
line = reader.readLine();
}
}
String newText = builder.toString();
Writing to a temporary file is a good solution too, though. The amount of I/O, which is the slowest to handle, is the same in both cases - read the full content once, write result once.

Reading a file's name from a text field and displaying it

I'm trying to make a program that reads a file name through a text field and displays it in a text area. I will also need a clear button. This is what I have so far:
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
String fileName = jTextField1.getText();
try {
FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr);
String s;
while ((s = br.readLine()) != null) {
jTextArea1.setText(s + "\n");
}
br.close();
} catch (IOException e) {
jTextArea1.setText("File not found!");
}
}
private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {
jTextField1.setText("");
jTextArea1.setText("");
}
For some reason, it is not reading my text file on my desktop, called "hi". How could I make my program work? What am I doing wrong?
setText does that, sets the text of the field
Now, JTextArea has a simple read method for reading content, for example
try (BufferedReader reader = new BufferedReader(new FileReader(new File("resources/New Text Document.txt")))) {
textArea.read(reader, "File");
} catch (IOException exp) {
exp.printStackTrace();
}
I'm not sure about your problem but this seems not right to me and I want to mention to you to fix it:
Actually what you do is putting the last line of text in your textArea1 and if your last line is "\n" or an empty line, then obviously you don't see anything on your screen.
It would be good to use StringBuffer to store your lines which are read from the file and display the whole text. The following code can help you:
StringBuffer buffer = new StringBuffer();
String s;
while ((s = br.readLine()) != null) {
buffer.append(s).append('\n');
}
jTextArea1.setText(buffer.toString());
your code is actually working and it is reading the file, but your code goes wrong inside the while loop when you are assigning the value you are not concating string inside the while loop i have made some changes to your code try this one.
String fileName = "src/hi.txt";
String content = "";
try {
FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr);
String s;
while ((s = br.readLine()) != null) {
content+="\n"+s;
}
System.out.println(content);
br.close();
} catch (Exception e) {
System.out.println("file not found");
}

Reading multiple text file in Java

I have few text files. Each text file contains some path and/or the reference of some other file.
File1
#file#>D:/FilePath/File2.txt
Mod1>/home/admin1/mod1
Mod2>/home/admin1/mod2
File2
Mod3>/home/admin1/mod3
Mod4>/home/admin1/mod4
All I want is, copy all the paths Mod1, Mod2, Mod3, Mod4 in another text file by supplying only File1.txt as input to my java program.
What I have done till now?
public void readTextFile(String fileName){
try {
br = new BufferedReader(new FileReader(new File(fileName)));
String line = br.readLine();
while(line!=null){
if(line.startsWith("#file#>")){
String string[] = line.split(">");
readTextFile(string[1]);
}
else if(line.contains(">")){
String string[] = line.split(">");
svnLinks.put(string[0], string[1]);
}
line=br.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Currently my code reads the contents of File2.txt only, control does not come back to File1.txt.
Please ask if more inputs are required.
First of all you are jumping to another file without closing the current reader and when you come back you lose the cursor. Read one file first and then write all its contents that match to another file. Close the current reader (Don't close the writer) and then open the next file to read and so on.
Seems pretty simple. You need to write your file once your svnLinks Map is populated, assuming your present code works (haven't seen anything too weird in it).
So, once the Map is populated, you could use something along the lines of:
File newFile = new File("myPath/myNewFile.txt");
// TODO check file can be written
// TODO check file exists or create
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try {
fos = new FileOutputStream(newFile);
osw = new OutputStreamWriter(fos);
bw = new BufferedWriter(osw);
for (String key: svnLinks.keySet()) {
bw.write(key.concat(" my separator ").concat(svnLinks.get(key)).concat("myNewLine"));
}
}
catch (Throwable t) {
// TODO handle more gracefully
t.printStackTrace();
if (bw != null) {
try {
bw.close();
}
catch (Throwable t) {
t.printStackTrace();
}
}
Here is an non-recursive implementation of your method :
public static void readTextFile(String fileName) throws IOException {
LinkedList<String> list = new LinkedList<String>();
list.add(fileName);
while (!list.isEmpty()) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(new File(list.pop())));
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("#file#>")) {
String string[] = line.split(">");
list.add(string[1]);
} else if (line.contains(">")) {
String string[] = line.split(">");
svnLinks.put(string[0], string[1]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
br.close();
}
}
}
Just used a LinkedList to maintain the order. I suggest you to add some counter if you to limit the reading of files to a certain number(depth). eg:
while (!list.isEmpty() && readCount < 10 )
This will eliminate the chance of running the code to infinity(in case of circular reference).

Modifying existing file content in Java

I want to replace the second line file content, can somebody help please based on the below file format and listener method.
1324254875443
1313131
Paid
0.0
2nd line is long and want to replace to currentTimeMillis().
/************** Pay Button Listener **************/
public class payListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
ArrayList<String> lines = new ArrayList<String>();
String line = null;
try {
FileReader fr = new FileReader("Ticket/" + ticketIDNumber + ".dat");
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter("Ticket/" + ticketIDNumber + ".dat");
BufferedWriter bw = new BufferedWriter(fw);
while ((line = br.readLine()) != null) {
if (line.contains("1313131"))
line.replace(System.currentTimeMillis();
lines.add(line);
bw.write(line);
} //end if
} //end try
catch (Exception e) {
} //end catch
} //end while
}//end method
Although this question is very old I'd like to add that this can be achieved much easier since Java 1.7 with java.nio.file.Files:
List<String> newLines = new ArrayList<>();
for (String line : Files.readAllLines(Paths.get(fileName), StandardCharsets.UTF_8)) {
if (line.contains("1313131")) {
newLines.add(line.replace("1313131", ""+System.currentTimeMillis()));
} else {
newLines.add(line);
}
}
Files.write(Paths.get(fileName), newLines, StandardCharsets.UTF_8);
As proposed in the accepted answer to a similar question:
open a temporary file in writing mode at the same time, and for each line, read it, modify if necessary, then write into the temporary file. At the end, delete the original and rename the temporary file.
Based on your implementation, something similar to:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class ReplaceFileContents {
public static void main(String[] args) {
new ReplaceFileContents().replace();
}
public void replace() {
String oldFileName = "try.dat";
String tmpFileName = "tmp_try.dat";
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(oldFileName));
bw = new BufferedWriter(new FileWriter(tmpFileName));
String line;
while ((line = br.readLine()) != null) {
if (line.contains("1313131"))
line = line.replace("1313131", ""+System.currentTimeMillis());
bw.write(line+"\n");
}
} catch (Exception e) {
return;
} finally {
try {
if(br != null)
br.close();
} catch (IOException e) {
//
}
try {
if(bw != null)
bw.close();
} catch (IOException e) {
//
}
}
// Once everything is complete, delete old file..
File oldFile = new File(oldFileName);
oldFile.delete();
// And rename tmp file's name to old file name
File newFile = new File(tmpFileName);
newFile.renameTo(oldFile);
}
}
I could suggest to use Apache Commons IO library. There you'll find the class org.apache.commons.io.FileUtils. You can use it:
File file = new File("... your file...");
List<String> lines = FileUtils.readLines(file);
lines.set(1, ""+System.currentTimeMillis());
FileUtils.writeLines(file, lines);
This code reads entire file contents into a List of Strings and changes the second line's content, then writes the list back to the file.
I'm not sure reading and writing the same file simultaneously is a good idea. I think it would be better to read the file line by line into a String array, replace the second line and then write the String array back into the file.

Categories