FileWriter not appending to existing file - java

I am writing a method that takes in a List of Twitter Status objects as a parameter, opens a log file containing String represenatations of Tweets, checks if any of the String representations of the Status objects are already written to the file - if so, it removes them from the list, if not it appends the Status to the file.
Everything is working up until I attempt to write to the file. Nothing is being written at all. I am led to believe that it is due to the method having the file open in two different places: new File("tweets.txt") and new FileWriter("tweets.txt, true).
Here is my method:
private List<Status> removeDuplicates(List<Status> mentions) {
File mentionsFile = new File("tweets.txt");
try {
mentionsFile.createNewFile();
} catch (IOException e1) {
// Print error + stacktrace
}
List<String> fileLines = new ArrayList<>();
try {
Scanner scanner = new Scanner(mentionsFile);
while (scanner.hasNextLine()) {
fileLines.add(scanner.nextLine());
}
scanner.close();
} catch (FileNotFoundException e) {
// Print error + stacktrace
}
List<Status> duplicates = new ArrayList<>();
for (Status mention : mentions) {
String mentionString = "#" + mention.getUser().getScreenName() + " \"" + mention.getText() + "\" (" + mention.getCreatedAt() + "\")";
if (fileLines.contains(mentionString)) {
duplicates.add(mention);
} else {
try {
Writer writer = new BufferedWriter(new FileWriter("tweets.txt", true));
writer.write(mentionString);
} catch (IOException e) {
// Print error + stacktrace
}
}
}
mentions.removeAll(duplicates);
return mentions;
}

I wrote here few thoughts looking your code.
Remember to always close the object Reader and Writer.
Have a look at try-with-resources statement :
try (Writer writer = new BufferedWriter(new FileWriter("tweets.txt", true))) {
writer.write(mentionString);
} catch (IOException e) {
// Print error + stacktrace
}
To read an entire file in a List<String>:
List<String> lines = Files.readAllLines(Paths.get("tweets.txt"), StandardCharsets.UTF_8);
And again, I think it's a bad practice write in the same file you're reading of.
I would suggest to write in a different file if you don't have a particular constraint.
But if you really want have this behavior there are few alternative.
Create a temporary file as output and, when you process is successfully completed, than move it to the old one using Files.move(from, to).

Related

Java - Delete file after reading from it

I am trying to figure out why my inputFile.delete() will not delete the file. After looking at numerous topics it looks like something is still using the file and hence it won't delete. But I can't figure it out. What am I missing??
File inputFile = new File("data/Accounts.txt");
File tempFile = new File("data/tmp.txt");
try {
tempFile.createNewFile();
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String line;
int i = 0;
for (User u : data) {
String toRemove = getIDByUsername(username);
while ((line = reader.readLine()) != null) {
if (line.contains(toRemove + " ")) {
line = (i + " " + username + " " + getStatusByUsername(username) + " " + password);
}
writer.write(line + "\n");
i++;
}
}
reader.close();
writer.close();
} catch (FileNotFoundException e) {
ex.FileNotFound();
} catch (IOException ee) {
ex.IOException();
} finally {
inputFile.delete();
tempFile.renameTo(inputFile);
}
You can have that much shorter and easier by using java.nio:
public static void main(String[] args) {
// provide the path to your file, (might have to be an absolute path!)
Path filePath = Paths.get("data/Accounts.txt");
// lines go here, initialize it as empty list
List<String> lines = new ArrayList<>();
try {
// read all lines (alternatively, you can stream them by Files.lines(...)
lines = Files.readAllLines(filePath);
// do your logic here, this is just a very simple output of the content
System.out.println(String.join(" ", lines));
// delete the file
Files.delete(filePath);
} catch (FileNotFoundException fnfe) {
// handle the situation of a non existing file (wrong path or similar)
System.err.println("The file at " + filePath.toAbsolutePath().toString()
+ " could not be found." + System.lineSeparator()
+ fnfe.toString());
} catch (FileSystemException fse) {
// handle the situation of an inaccessible file
System.err.println("The file at " + filePath.toAbsolutePath().toString()
+ " could not be accessed:" + System.lineSeparator()
+ fse.toString());
} catch (IOException ioe) {
// catch unexpected IOExceptions that might be thrown
System.err.println("An unexpected IOException was thrown:" + System.lineSeparator()
+ ioe.toString());
}
}
This prints the content of the file and deletes it afterwards.
You will want to do something different instead of just printing the content, but that will be possible, too ;-) Try it...
I am trying to figure out why my inputFile.delete() will not delete the file.
That's because the old file API is crappy specifically in this way: It has no ability to tell you why something is not succeeding. All it can do, is return 'false', which it will.
See the other answer, by #deHaar which shows how to do this with the newer API. Aside from being cleaner code and the newer API giving you more options, the newer API also fixes this problem where various methods, such as File.delete(), cannot tell you the reason for why it cannot do what you ask.
There are many, many issues with your code, which is why I strongly suggest you go with deHaar's attempt. To wit:
You aren't properly closing your resources; if an exception happens, your file handlers will remain open.
Both reading and writing here is done with 'platform default encoding', whatever that might be. Basically, never use those FileReader and FileWriter constructors. Fortunately, the new API defaults to UTF_8 if you fail to specify an encoding, which is more sensible.
your exception handling is not great (you're throwing away any useful messages, whatever ex.FileNotFound() might be doing here) - and you still try to delete-and-replace even if exceptions occur, which then fail, as your file handles are still open.
The method should be called getIdByUsername
Your toRemove string is the same every time, or at least, the username variable does not appear to be updated as you loop through. If indeed it never updates, move that line out of your loop.

Java too many open files exception

I have a problem on my code; basically I have an array containing some key:
String[] ComputerScience = { "A", "B", "C", "D" };
And so on, containing 40 entries.
My code reads 900 pdf from 40 folder corresponding to each element of ComputerScience, manipulates the extracted text and stores the output in a file named A.txt , B.txt, ecc ...
Each folder "A", "B", ecc contains 900 pdf.
After a lot of documents, an exception "Too many open files" is thrown.
I'm supposing that I am correctly closing files handler.
static boolean writeOccurencesFile(String WORDLIST,String categoria, TreeMap<String,Integer> map) {
File dizionario = new File(WORDLIST);
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
File cat_out = new File("files/" + categoria + ".txt");
fileWriter = new FileWriter(cat_out, true);
} catch (IOException e) {
e.printStackTrace();
}
try {
fileReader = new FileReader(dizionario);
} catch (FileNotFoundException e) { }
try {
BufferedReader bufferedReader = new BufferedReader(fileReader);
if (dizionario.exists()) {
StringBuffer stringBuffer = new StringBuffer();
String parola;
StringBuffer line = new StringBuffer();
int contatore_index_parola = 1;
while ((parola = bufferedReader.readLine()) != null) {
if (map.containsKey(parola) && !parola.isEmpty()) {
line.append(contatore_index_parola + ":" + map.get(parola).intValue() + " ");
map.remove(parola);
}
contatore_index_parola++;
}
if (! line.toString().isEmpty()) {
fileWriter.append(getCategoryID(categoria) + " " + line + "\n"); // print riga completa documento N x1:y x2:a ...
}
} else { System.err.println("Dictionary file not found."); }
bufferedReader.close();
fileReader.close();
fileWriter.close();
} catch (IOException e) { return false;}
catch (NullPointerException ex ) { return false;}
finally {
try {
fileReader.close();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
But the error still comes. ( it is thrown at:)
try {
File cat_out = new File("files/" + categoria + ".txt");
fileWriter = new FileWriter(cat_out, true);
} catch (IOException e) {
e.printStackTrace();
}
Thank you.
EDIT: SOLVED
I found the solution, there was, in the main function in which writeOccurencesFile is called, another function that create a RandomAccessFile and doesn't close it.
The debugger sais that Exception has thrown in writeOccurencesFile but using Java Leak Detector i found out that the pdf were already opened and not close after parsing to pure text.
Thank you!
Try using this utility specifically designed for the purpose.
This Java agent is a utility that keeps track of where/when/who opened files in your JVM. You can have the agent trace these operations to find out about the access pattern or handle leaks, and dump the list of currently open files and where/when/who opened them.
When the exception occurs, this agent will dump the list, allowing you to find out where a large number of file descriptors are in use.
i have tried using try-with resources; but the problem remains.
Also running in system macos built-in console print out a FileNotFound exception at the line of FileWriter fileWriter = ...
static boolean writeOccurencesFile(String WORDLIST,String categoria, TreeMap<String,Integer> map) {
File dizionario = new File(WORDLIST);
try (FileWriter fileWriter = new FileWriter( "files/" + categoria + ".txt" , true)) {
try (FileReader fileReader = new FileReader(dizionario)) {
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
if (dizionario.exists()) {
StringBuffer stringBuffer = new StringBuffer();
String parola;
StringBuffer line = new StringBuffer();
int contatore_index_parola = 1;
while ((parola = bufferedReader.readLine()) != null) {
if (map.containsKey(parola) && !parola.isEmpty()) {
line.append(contatore_index_parola + ":" + map.get(parola).intValue() + " ");
map.remove(parola);
}
contatore_index_parola++;
}
if (!line.toString().isEmpty()) {
fileWriter.append(getCategoryID(categoria) + " " + line + "\n"); // print riga completa documento N x1:y x2:a ...
}
} else {
System.err.println("Dictionary file not found.");
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
This is the code that i am using now, although the bad managing of Exception, why the files seem to be not closed?
Now i am making a test with File Leak Detector
Maybe your code raises another exception that you are not handling. Try add catch (Exception e) before finally block
You also can move BufferedReader declaration out the try and close it in finally

Write at the end of a file

I want to write in file the content of a list. The code is easy to understand and sometimes do the work. But the most of the times it fails. This is what i've tried so far :
public void finishTheTest(String outputFileName) throws FileNotFoundException{
StringBuilder testOutPutStringBuilder = new StringBuilder();
if(!isFieldSuccessFull) {
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append("Error for Task -> " + tm.getFieldHM(tm.getKey()));
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append("*****************************************");
testOutPutStringBuilder.append(System.getProperty("line.separator"));
for(String str : listFailure) {
testOutPutStringBuilder.append(str);
testOutPutStringBuilder.append(System.getProperty("line.separator"));
}
testOutPutStringBuilder.append("*****************************************");
testOutPutStringBuilder.append(System.getProperty("line.separator"));
}
if(!isCinematicSuccessFull) {
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append("Error for Repository -> " + tm.getFieldHM(tm.getKey()));
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append("*****************************************");
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append("Cinematic error.");
testOutPutStringBuilder.append(System.getProperty("line.separator"));
testOutPutStringBuilder.append("*****************************************");
testOutPutStringBuilder.append(System.getProperty("line.separator"));
}
try(PrintStream ps = new PrintStream( new FileOutputStream(outputFileName, true))) {
System.out.println(testOutPutStringBuilder);
ps.println(testOutPutStringBuilder.toString());
}
I'm browsing a list of String to build a StringBuilder or i simply append String to the StringBuilder. Then i print it on the standard output, wich is working and then i print it in the specified file. The file is created but most of the time it stays empty even after the execution of the code. Since i specified "true" at the creation of the FileOutputStream, i hoped that the text would simply add at the end at the file. But when i run the code more than once i have nothing left in the file.
Is there something that i'm missing ?
You are using try-with-resources, which leaves open the possibility of Suppressed Exceptions:
https://docs.oracle.com/javase/8/docs/technotes/guides/language/try-with-resources.html
If you look at the accepted answer here
Do I have to close FileOutputStream which is wrapped by PrintStream?
you can add a catch block to see if some exception is happening that you're missing.
You could temporarily change your code to something like this:
public void finishTheTest(String outputFileName) throws Exception {
...
try(PrintStream ps = new PrintStream( new FileOutputStream(outputFileName, true))) {
System.out.println(testOutPutStringBuilder);
ps.println(testOutPutStringBuilder.toString());
}
catch (Exception e) {
System.out.println("Error in writing to file:");
e.printStackTrace();
throw e;
}
...
}
then you will see any exception if it is thrown by your try().
I've found a solution to my problem. Instead of using this to write to my file :
try(PrintStream ps = new PrintStream( new FileOutputStream(outputFileName, true))) {
ps.println(testOutPutStringBuilder.toString());
}
I'm using this :
try(PrintWriter ps = new PrintWriter( new BufferedWriter(new FileWriter(outputFileName, true)))) {
ps.println(testOutPutStringBuilder.toString());
}
This is working every time from a while now. I still don't know what was wrong with the other code.

Filewriter issues - Java Android

My filewriter does not seem to create a file. This is my code:
public void peopledetails_write(ArrayList<PeopleDetails> peopledetails_file) {
////numbers is the arraylist of numbers.
///names is the arraylist of names of people.
///Written to file like 01235 678 908, Daniel; 01245 645 123, Bob Marley; etc.
///Like a CSV file.
try{
FileWriter writer_file = new FileWriter("PeopleDetailsFile");
String filestring = ""; ///initializes filestring, which is written to the file.
for(PeopleDetails person : peopledetails_file){
String person_detail_string = "";
person_detail_string = person.name + "," + person.number;
filestring = filestring + person_detail_string + ";";
}
writer_file.write(filestring);
writer_file.close();
}
catch (IOException e) {
Log.e("ERROR", e.toString());
}finally{
///Hopefully won't get an error here.
Intent switch_menu = new Intent(this, MenuList.class);
startActivity(switch_menu);
}
}
It acts on the finally, and takes the user back to the main menu of my app. I have managed to debug the section where this code is, and reckon that this is faulty code, as I get a FileNotFound exception, after this section should have written a file.
What is wrong with this code?
here where your going wrong, unless api points to some specific directory, you should always
use absolute file path(complete file path).
FileWriter writer_file = new FileWriter(complete_file_path);

Problem updating list of data

private static void deleteProxy(File proxyOld, String host, int port) {
try {
String lines, tempAdd;
boolean removeLine = false;
File proxyNew = new File("proxies_" + "cleaner$tmp");
BufferedReader fileStream = new BufferedReader(new InputStreamReader(new FileInputStream(proxyOld)));
BufferedWriter replace = new BufferedWriter(new FileWriter(proxyNew));
while ((lines = fileStream.readLine()) != null) {
tempAdd = lines.trim();
if (lines.trim().equals(host + ":" + port)) {
removeLine = true;
}
if (!removeLine) {
replace.write(tempAdd);
replace.newLine();
}
}
fileStream.close();
replace.close();
proxyOld.delete();
proxyNew.renameTo(proxyOld);
} catch (Exception e) {
e.printStackTrace();
}
}
Calling the function:
File x = new File("proxies.txt");//is calling a new file the reason why it's being flushed out?
deleteProxy(x, host, port);
Before I run the program the file proxies.txt had data inside of it. However when I run the program it appears to be flushed out. It becomes empty.
I noticed while the program is running, if I move my mouse over the file proxies.txt, Windows displays the "Date Modified" and the time it displays is the current time, or last time the function deleteProxy(...) was executed.
Does anyone know what I'm doing wrong? And why won't the list update instead of appearing to be empty?
Updated code:
private static void deleteProxy(File proxyOld, String host, int port) {
try {
String lines, tempAdd;
boolean removeLine = false;
File proxyNew = new File("proxies_" + "cleaner$tmp");
FileInputStream in = new FileInputStream(proxyOld);
InputStreamReader read = new InputStreamReader(in);
BufferedReader fileStream = new BufferedReader(read);
FileWriter write = new FileWriter(proxyNew);
BufferedWriter replace = new BufferedWriter(write);
while ((lines = fileStream.readLine()) != null) {
tempAdd = lines.trim();
if (lines.trim().equals(host + ":" + port)) {
removeLine = true;
}
if (!removeLine) {
replace.write(tempAdd);
replace.newLine();
}
}
in.close();
read.close();
fileStream.close();
write.close();
replace.close();
if (proxyOld.delete()) {
throw new Exception("Error deleting " + proxyOld);
}
if (proxyNew.renameTo(proxyOld)) {
throw new Exception("Error renaming " + proxyOld);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Running the updated code it deletes proxies.txt just fine but it fails to make the new file:\
Maybe I should find a new method to update a text file, do you have any suggestions?
Your rename operation may not work, as per the File.renameTo() documentation:
Many aspects of the behavior of this method are inherently platform-dependent: The rename operation might not be able to move a file from one filesystem to another, it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists. The return value should always be checked to make sure that the rename operation was successful.
So basically, you're wiping your old file, and you're not guaranteed the new file will take its place. You must check the return value of File.renameTo():
if(proxyNew.renameTo(proxyOld)){
throw new Exception("Could not rename proxyNew to proxyOld");
}
As for why your renameTo may be failing: you're not closing the nested set of streams that you open to read from the old file, so the operating system may still consider an abstract pathname to exist. Try making sure you close all of the nested streams you open.
Try this:
FileInputStream in = new FileInputStream(proxyOld);
BufferedReader fileStream = new BufferedReader(new InputStreamReader(in));
...
in.close();

Categories

Resources