bluehypergiant.com
tagline here
Core Java I/O Classes with Poor Exception Handling
2012-02-19
I was working on an application the other day that was doing some simple file I/O with JCIFS. There was a rather strange problem -- the application wrote several records to the file on the network share and then seemingly "skipped" several before continuing to write to the end of the file. It turned out that the file server was unavailable during that short amount of time, which I found strange because the application did not fail as it normally would with that kind of error.

The problem
Digging into it further, I found that some classes in core Java do not properly handle exceptions, IMO:
  • java.util.Scanner
  • java.io.PrintWriter
  • java.io.PrintStream
PrintWriter and PrintStream require the user to call their "checkError()" methods to determine if the "last operation" caused an exception. So writing code like this:
...
//Get SMBFileOutputStream from JCIFS to write to file server
...
PrintWriter pw = new PrintWriter(smbFileOutputStream);
for(String dataLine : dataLines) {
	pw.printLine(dataLine);
}
...
will result in any issues with the writing of data to be undetected.
Scanner requires the user to call its "ioException()" method to determine if the "last operation" caused an exception. This code does not properly detect issues with reading data:
...
//Get SMBFileInputStream from JCIFS to read from a file server
...
String line = null;
Scanner s = new Scanner(smbFileInputStream);
while(s.hasNextLine()) {
	line = s.nextLine();
}

The solution
Instead of using Scanner, PrintWriter or PrintStream, I recommend using:
  • java.io.BufferedReader
  • java.io.BufferedWriter
These examples properly handle exceptions in the underlying code:
...
//Get SMBFileInputStream from JCIFS to read from a file server
...
BufferedReader br = new BufferedReader(smbFileInputStream);
String line = br.readLine();
while(line != null) {
	//do something with the line...
	line = br.readLine();
}
...

...
//Get SMBFileOutputStream from JCIFS to write to file server
...
BufferedWriter bw = new BufferedWriter(smbFileOutputStream);
for(String dataLine : dataLines) {
	bw.write(dataLine);
	bw.newLine();
}
...