Interesting question.
I just peeked into each constructor's code, which helped clarify things:
FileWriter uses a FileOutputStream. The FileOutputStream throws a FileNotFoundException, which extends IOException.
FileWriter extends OutputStreamWriter whose constructor throws UnsupportedEncodingException, which also extends IOException.
FileWriter, therefore, can throw either exception. But since they both extend IOException, it declares IOException in its constructor's signature.
All your objects and all their fields need to be serializable - otherwise they can not be serialized. Another source of IO exception would be lack of permission to write on SD card. ( does somebody except your application needs this data? if not, it belongs into provate area.)
Serializing config data is convenient, but may be bad idea - if your object signature changes, data will be unreadable. Better solution would be to marshall objects into JSON and save this file ( Shameless self advertising on: https://github.com/ko5tik/jsonserializer )
Although Konstantin Pribluda identified a better solution for what I needed to do, this question has been solved.
Turned out I stupidly overlooked the fact that my Event and State classes didn't implement Serializable. Any fields within a Serializable class must also be Serializable, otherwise the IO Exception is thrown.
While working on BufferedOutputStream found it does not throw an IOException when we wrote on it after closing the stream.
The BufferedOutputStream code just doesn't have that sort of checking – but then neither does the FileOutputStream. In both cases, only when the IO is actually written to disk does the OS "throw" the IOException. It is not the Java code which is detecting that the stream has been closed. As an aside, this probably means that some native implementations don't throw at all.
The reason why the FileOutputStream is throwing the exception on os.write(...), versus the BufferedOutputStream, is that it is writing the IO to the underlying native layer immediately. If you add a os.flush() call to the BufferedOutputStream after the os.write() then you will see the same exception because that forces its internal buffer to be written out.
OutputStream os = new BufferedOutputStream(new FileOutputStream("abc.txt", false));
os.write(barry1);
os.close();
os.write(barray2); // this suceeds – unfortunate behavior
os.flush(); // adding this line throws an IOException
In looking at the BufferedOutputStream's close() method (actually in the FilterOutputStream base class), you can see that the output stream is not set to null or anything:
public void close() throws IOException {
try {
flush();
} catch (IOException ignored) {
}
out.close();
}
I also don't like the fact that it is ignoring IOExceptions on close here. Wow. This tells me that we should always call flush() by hand before close() which is a pattern I specifically don't do.
Now compare that code to the BufferedWriter.close():
public void close() throws IOException {
synchronized (lock) {
if (out == null) {
return;
}
try {
flushBuffer();
} finally {
out.close();
out = null; // good doggie
cb = null;
}
}
}
BufferedWriter.close() doesn't eat the exception and sets the delegated Writer to be null. Much better IMO.
Because BufferedOutputStream writes bytes to its internal byte buffer, then when invoked writes to the underlying ouput stream, so if call flush after the os.write(c);, it will throw the exception, but here you try to write to the file stream directly after it was closed, hence the exception, no surprise here
When I tried this, it didn't even compile. I had to say that the main throws FileNotFoundException
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
public class FileIO
{
public static void main(String[] args) throws FileNotFoundException
{
File test = new File("test.txt");
FileOutputStream ostream = new FileOutputStream(test);
PrintWriter out = new PrintWriter(ostream);
}
}
This worked just fine with no errors
The answer is undoubtedly that the current directory isn't what you think it is.
Add this line of code immediately after initializing the file variable:
System.out.println(test.getAbsolutePath());
The problem should be obvious.
Alternatively, specify an absolute path:
File test = new File("/mydir/test.txt");