Java writing to textfiles not completing - java

I'm using a BufferedWriter to write some data to a textfile. It's faster than using ODBC to write to Access. Code looks something like this:
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(filePath), true));
True is to make the BufferedWriter append, not overwrite.
bw.append(
country + "\t" +
scenario + "\t" +
tempStage + "\t" +
year + "\t" +
tempState
);
It's worked for me in previous projects. New problem: it just craps out in the middle of the line. This is a good line:
SultanateOfBrunei BeeBeeScenario Other 2019
The last line typically looks like this:
SultanateOfBrunei BeeBeeScenario Other 2019 Nondyna
or
Sulta
or even
Su
I put in error handling code to ignore weird incomplete lines like that.
This means not all the data is being written. I can give up one datum, no problem... But it appears to be cutting out more. The simulation runs 1990 to the end of 2020 and it typically craps out somewhere in 2019. Increasing the VM helps a little-- it gets further. But I only have a certain amount of memory!
Any insights?
Thanks!!

Your application is probably not closing the BufferedWriter, and as a result the last part of the output is not being written out to the file.
The structure of your program should be something like this:
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(filePath), true));
try {
// generate output
} finally {
bw.close();
}
Note that this doesn't attempt to handle the I/O exceptions that might arise while opening, writing to or closing the writer. Whether you should do that, and what you should do with any exceptions that you catch depends on the circumstances.

Probably you are not flushing (bw.flush()) the stream before closing it. That should be done to all streams, but it is more critical to buffered ones.

You just need to close the BufferedWriter. If you dont, the last filled buffer might not get written.

Once you're done writing, you should essentially call close() on your BufferedWriter object. This would ensure that the your stream is flushed and consequently closed.

Related

Is there a line limit when writing to a txt file using Java?

I'm trying to keep a log of http responses with writing them in a txt file.
I'm using the FileWriter in Java, but unfortunately when the number of lines (e.g. 1000 lines) or the size of the txt file (e.g. 80kb) is exceeded, it automatically removes the previous content and writes the new ones.
This happens every time the limit is exceeded.
try{
File file = new File("response.txt");
file.createNewFile();
FileWriter writer = new FileWriter(file,true);
writer.write(+System.currentTimeMillis()+"\t"+response+"\n");
writer.flush();
writer.close();}
catch(IOException ioe){
System.out.println("\nError");}
file.createNewFile();
Here you are creating a new file every time you call this method.
FileWriter writer = new FileWriter(file,true);
Here you are trying to append to an existing file, which no longer exists because of the prior File.createNewFile(). So you are losing all your prior output and writing to a new file every time you call this method. Remove it.
This kind of second-guessing is always and everywhere a complete waste of time and space. new FileWriter() already has to do all that anyway, and you're just forcing it to happen twice: in this case, erroneously.
In fact you should try to keep the file open rather than reopening and reclosing it every time you call this method. What you're doing is horrifically inefficient. As well as not working.
NB When you get an exception, print the exception. Not just "error". Otherwise next thing you know you will be asking here why it prints "error", just because you didn't write your code properly.
I am guessing it's either because:
There's not enough disk space.
file.createNewFile() is being used for every line and it's not reliable.
You open and close the stream for every line.
You call this code in a multithreaded environment without synchronising.
Try the following:
BufferedWriter out = null;
try
{
out = new BufferedWriter(new FileWriter(file, true));
out.append(response);
out.newLine();
} catch(Exception e)
{
e.printStackTrace(); // if needed
out.append("Error");
out.newLine();
}
finally
{
ResourceUtil.closeQuietly(out);
}

PrintWriter--No Output?

EDIT: Fixed! Was overwriting file instead of appending to the file.
I seem to have a bit of a problem trying to use a PrintWriter to add a "header" to a log file before use, so that my program knows that it is not just a random text file. The field output_file refers to an argument taken by the logger initialization function to set the log file, whereas log_file is a static file field for the (global and static) logging class. After opening the log file to check for errors, there is no header. Using logging functions, also carried out by a PrintWriter, gives the correct output. Am I doing something wrong? (I know I am reinventing the wheel as a logging API already exists for Java, but I am working on a learning exercise.)
//After testing to make sure the file specified does not exist
log_file=output_file;
output_file.createNewFile();
PrintWriter pw=new PrintWriter(log_file);
pw.println("**[PROGRAM_NAME Log]**");
pw.flush();
pw.close();
isInitialized=true;
EDIT: The file is definitely writable, or the logger itself wouldn't work. Also, for those who were wondering, the code to log something is the following (Same general method as writing the header AKA new PrintWriter(log_file);)
PrintWriter pw = new PrintWriter(log_file);
pw.print("[INFO:] " + sdf.format(new Date())); //The variable sdf is a date formatter for timestamps.
pw.println(" " + message);
pw.close();
The documentation for PrintWriter says:
file - The file to use as the destination of this writer. If the file
exists then it will be truncated to zero size; otherwise, a new file
will be created. The output will be written to the file and is
buffered.
So every time you use new Printwriter(log_file), you are actually truncating the file, erasing everything in it, and starting fresh.
This means, of course, that as soon as you start logging, the header data gets erased.
If you want to append to the file, rather than erase it every time, you need to open a FileOutputStream with the append option, and open the PrintWriter on top of it.
try (
FileOutputStream os = new FileOutputStream(log_file, true);
PrintWriter pw = new PrintWriter(os);
) {
pw.println("Your log line here");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
(Note the use of try-with-resources to auto-close the file when work with it is done. Of course, you can just keep it opened until you finish logging. This is merely an example.).

about the close method() used for closing a stream

Today, when I was working on some kind of servlet which was writing some information to some file present on my hard disk, I was using the following code to perform the write operation
File f=new File("c:/users/dell/desktop/ja/MyLOgs.txt");
PrintWriter out=new PrintWriter(new FileWriter(f,true));
out.println("the name of the user is "+name+"\n");
out.println("the email of the user is "+ email+"\n");
out.close(); //**my question is about this statement**
When I was not using the statement, the servlet was compiling well, but it was not writing anything to the file, but when I included it, then the write operation was successfully performed. My questions are:
Why was the data not being written to the file when I was not including that statement (even my servlet was compiling without any errors)?
Up to which extent the close operation is considerable for the streams?
Calling close() causes all the data to be flushed. You have constructed a PrintWriter without enabling auto-flush (a second argument to one of the constructors), which would mean you would have to manually call flush(), which close() does for you.
Closing also frees up any system resources used by having the file open. Although the VM and Operating System will eventually close the file, it is good practice to close it when you are finished with it to save memory on the computer.
You may also which to put the close() inside a finally block to ensure it always gets called. Such as:
PrintWriter out = null;
try {
File f = new File("c:/users/dell/desktop/ja/MyLOgs.txt");
out = new PrintWriter(new FileWriter(f,true));
out.println("the name of the user is "+name+"\n");
out.println("the email of the user is "+ email+"\n");
} finally {
out.close();
}
See: PrintWriter
Sanchit also makes a good point about getting the Java 7 VM to automatically close your streams the moment you don't need them automatically.
When you close a PrintWriter, it will flush all of its data out to wherever you want the data to go. It doesn't automatically do this because if it did every time you wrote to something, it would be very inefficient as writing is not an easy process.
You could achieve the same effect with flush();, but you should always close streams - see here: http://www.javapractices.com/topic/TopicAction.do?Id=8 and here: http://docs.oracle.com/javase/tutorial/jndi/ldap/close.html. Always call close(); on streams when you are done using them. Additionally, to make sure it is always closed regardless of exceptions, you could do this:
try {
//do stuff
} finally {
outputStream.close():
}
It is because the PrintWriter buffers your data in order for not making I/O operations repeatedly for every write operation (which is very expensive). When you call close() the Buffer flushes into the file. You can also call flush() for forcing the data to be written without closing the stream.
Streams automatically flush their data before closing. So you can either manually flush the data every once in a while using out.flush(); or you can just close the stream once you are done with it. When the program ends, streams close and your data gets flushed, this is why most of the time people do not close their streams!
Using Java 7 you can do something like this below which will auto close your streams in the order you open them.
public static void main(String[] args) {
String name = "";
String email = "";
File f = new File("c:/users/dell/desktop/ja/MyLOgs.txt");
try (FileWriter fw = new FileWriter(f, true); PrintWriter out = new PrintWriter(fw);) {
out.println("the name of the user is " + name + "\n");
out.println("the email of the user is " + email + "\n");
} catch (IOException e) {
e.printStackTrace();
}
}
PrintWriter buffers the data to be written so and will not write to disk until its buffer is full. Calling close() will ensure that any remaining data is flushed as well as closing the OutputStream.
close() statements typically appear in finally blocks.
Why the data was not being written to the file when I was not including that statement?
When the process terminates the unmanaged resources will be released. For InputStreams this is fine. For OutputStreams, you could lose an buffered data, so you should at least flush the stream before exiting the program.

"\n" not working when exported to .jar file

I have an output file for a program I have written. It is written by a FileWriter and BufferedWriter.
FileWriter errout = new FileWriter(new File("_ErrorList.txt"));
BufferedWriter out = new BufferedWriter(errout);
Later I write to the file using lines similar to.
out.write("Product id:" + idin + " did not fetch any pictures.\n ");
When I simpily run the program in Eclipse, the output file is formatted correctly, with each message being written on a new line. However when I export to a .jar file, it no longer works and puts every message on a single line, as if the "\n" was not working.
Am I using the FileWriter/BufferedWriter incorrectly, or does it not work in a .jar file?
You should not use '\n' directly. Either use out.newLine() to introduce a line break, or wrap the BufferedWriter into a PrintWriter, and use out.println().
This has nothing to do with the .jar file, anyway. More likely is Eclipse being clever and showing you line breaks, while the operating system does not.
One, check that the line separator is valid. Use System.getProperty("line.separator") as provided by #Andrew Thompson.
Another option if you're doing a lot of this writing new lines is to wrap your BufferedWriter in a PrintWriter.
FileWriter errout = new FileWriter(new File("_ErrorList.txt"));
BufferedWriter out = new BufferedWriter(errout);
PrintWriter printWriter = new PrintWriter(out);
printWriter.println("Product id:" + idin + " did not fetch any pictures.");

Having issues in writing text files

I am using the FileWriter class to write text files in Java.
The "\n" is not working, so to overcome this I used the BufferedWriter class and its method newLine(). It helped me getting onto next line but alas, it always go on modifying my previous file. I want every time when I run my program a new file to be generated!
Please someone help me on this part. Why is that "\n" not working? What is the possible solution to my problem?
FileWriter write = new FileWriter ("D:/final project/report.txt", true);
BufferedWriter bufferedWriter = new BufferedWriter (write);
bufferedWriter.write("Current Time : " + hour + ":"+ minute + ":" + second + " " + am_pm);
bufferedWriter.newLine();
bufferedWriter.write("Current Date : " + date + "/"+ (month+1) + "/" + year + " d/m/y ");
bufferedWriter.newLine();
You've really got two entirely orthogonal problems here...
I want every time when I run my program a new file to be generated!
Well currently this is how you're creating the FileWriter:
new FileWriter ("D:/final project/report.txt", true);
That's using the constructor overload with an append parameter, which you're setting to true... suggesting you want to append to an existing file.
If you don't want to append to an existing file, why are you specifying true for that parameter? Either specify false instead, or just use an overload which doesn't have that parameter, and overwrites the file by default.
Personally I would strongly advise against using FileWriter directly - I'd use FileOutputStream wrapped in an OutputStreamWriter, so that you can specify the encoding. Otherwise it will use the platform default encoding, which is rarely a good idea IMO. (Personally I tend to use UTF-8 when I have the choice.)
Why is that "\n" not working?
It's working in that it's writing the \n character (U+000A) to the file. But whatever you're using to read that file presumably isn't treating that as a line break - because the line break on Windows is usually \r\n. BufferedWriter.newLine() will use the platform default line break, which is why that's working.
Use the correct line separator:
String lineSep = System.getProperty("line.separator");
You can use FileOutputStream and wrap it in DataOutputStream
FileOutputStream fo=new FileOutputStream("c:/xyz/report.txt");
DataOutputStream ds=new DataOutputStream(fo);
ds.writeBytes("Current Time : " +new Date() );
ds.writeBytes(System.getProperty("line.separator")+"Current Date : " +new Date() );
Java terminates each line with a carriage return and line feed instead of just a line feed. That is Java terminates using "\r\n" instead of "\n".

Categories