I have a simple servlet where I write to a file if it has a queryparameter 'hello', and since this is a test I want to display the error the the webpage also.
IntelliJ is complaining that I am not catching the IOException, not sure what's wrong:
private static void WriteToFile(String filePath, String fileName, String fileData) {
FileWriter writer = null;
try {
writer = new FileWriter(fileName);
writer.write(fileData);
} catch(IOException ex) {
} finally {
if(writer != null) {
writer.close();
}
}
}
Also, in my exception, I noticed on the web most people write:
How can I output the error to the web page?
You're not catching IOException when you call writer.close(); in the finally block.
You're also completely swallowing any IOException thrown in the main code, which is a really bad idea. If something's goes wrong, you'll have no idea what's happening.
I would personally suggest that you let that method throw the exception to the caller:
private static void writeToFile(String filePath, String fileName,
String fileData) throws IOException {
FileWriter writer = new FileWriter(fileName);
try {
writer.write(fileData);
} finally {
writer.close();
}
}
Note that if the try block throws an exception and the finally block does, you'll effectively "lose" the original exception. You may want to suppress exceptions throw when closing.
Or just use Guava which makes all of this simpler anyway with its Files class.
Or if you're using Java 7, you could use a try-with-resources statement.
(I note that you're ignoring filePath by the way - why?)
You can write in catch block too : writer.write(errorMessage);
or you may redirect to Error page if error occured
Related
I have this code but there is an error to this,
I am not good with java so I posted my problem in here... this is my code
public static void SaveFile() throws IOException{
System.out.println("Saving File!");
FileWriter toTextFile = new FileWriter("output.txt");
for(x=0;x<new_num_book;x++){
toTextFile.write(name[x]);
}
toTextFile.close();
}
blah blah
else if(option == 5){
SaveFile();
}
the problem is that netbeans declares an error in accessing the SaveFile function. Please help! Thanks
saveFile throws an IOException, you need to handle it or pass it on to the caller.
Take a look at The try Block for more details
Without more context it's hard to say what you should do. You could handle the exception within the current method...
else if(option == 5){
try {
SaveFile();
} catch (IOException exp) {
// Handle the exception, tell the user, roll back, what ever
// At the very least use exp.printStackTrace()
}
}
or declare the current method as throwing an IOException like the SaveFile method does
Your SaveFile method is also, potentially, leaving the file open...
If the file writing process fails for some reason, toTextFile.close may never be called, instead, you should take advantage of the try-finally block, for example
public static void SaveFile() throws IOException{
System.out.println("Saving File!");
FileWriter toTextFile = null;
try {
toTextFile = new FileWriter("output.txt");
for(x=0;x<new_num_book;x++){
toTextFile.write(name[x]);
}
} finally {
try {
toTextFile.close();
} catch (Exception exp) {
}
}
}
or if you're using Java 7+, you can make use of the try-with-resources functionality, for example...
public static void SaveFile() throws IOException{
System.out.println("Saving File!");
try (FileWriter toTextFile = new FileWriter("output.txt")) {
for(x=0;x<new_num_book;x++){
toTextFile.write(name[x]);
}
}
}
You may also want to have a read of Lesson: Exceptions and Code Conventions for the Java TM Programming Language, which will make it easier for people to read your code and for you to read others
Im trying to create a log file for a small chatroom I've created.
so far this is what I have for the logging:
static void log(String s){
try{
BufferedWriter writer =
new BufferedWriter(new FileWriter("log"+getTime()+".txt"));
writer.write(s);
}catch(IOException e){
e.printStackTrace();
}
}
I call it in this way in a thread for each connection each time I brodcast to the clients:
log(name+"String")
but after its called and doesn't continue the program. however, when this did work, the only thing in the text file would be one line, the first one called. how can one fix both these bugs?
As stated in the other answers, you don't close the file and you are not writing a line separator.
I see that there's one perfect answer in Java 7, but you said in the comments that you are not able to use that. (I suppose you are using Java 6 instead)
Because of that, I have written an implementation using only Java 6 API (using the Java 6 javadocs for reference):
public class LogFileHelper {
private final BufferedWriter writer;
public LogFileHelper(File outputFile) throws IOException {
if(!outputFile.exists()){ //The JavaDoc says that it is not certain if the file will be created
outputFile.createNewFile();
}
this.writer = new BufferedWriter(new FileWriter(outputFile, true));
}
public void writeLine(String line) throws IOException {
if(line == null){
throw new IllegalArgumentException("line may not be null");
}
this.writer.write(line);
this.writer.newLine();
this.writer.flush(); //Make sure the line we just wrote is written and kept if the application crashes
}
public void tryWriteLine(String line) {
try {
writeLine(line);
} catch(IOException ioe){
//Your exception handling here
}
}
public void close() throws IOException {
this.writer.close();
}
public void tryClose() {
try {
this.writer.close();
} catch(IOException ioe){
//Your exception handling here
}
}
}
I added tryXXX methods to simplify exception handling, as I suppose you will use the same everywhere. I kept the base methods to allow for custom exception handling where needed.
With above class, you would store the instance somewhere, write to it where needed and close it on exit. Your best bet for that is a shutdown handler like this one:
Runtime.getRuntime().addShutdownHook(new Thread("Chatlog Shutdown Thread"){
#Override
public void run(){
myLogFileHelper.tryClose();
}
});
Where you would execute that statement just after you create your LogFileHelper instance.
The above code does flush every time you write something - If you want to go super efficient, you could flush less often. A valid use case for not flushing immediately would be when writing a whole batch of lines at once, although you always have to balance between not flushing and having the file on disk immediately.
Use try-with-resources and write in append mode:
static void log(String s) {
try (PrintWriter out = new PrintWriter(new BufferedWriter(
new FileWriter("log" + getTime() + ".txt", true)))) {
out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
You have several problems:
each time you log one statement you open a new file descriptor;
... which you don't close;
given on the output of .getTime() you may even write to several different files.
Use a dedicated class which you initialize and share once across all classes which use logging facilities; for instance a singleton.
In the constructor you would open the file:
private final BufferedWriter writer;
// ...
public MyLogFile()
throws IOException
{
final Path path = Paths.get("path to logfile");
writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
Use a method to write a line:
public void writeOneLine(#Nonnull final String line)
throws IOException
{
Objects.requireNonNull(line, "won't write null, sorry");
writer.write(line);
writer.newLine();
writer.flush();
}
As for closing the file when you exit, either make you class implement Closeable and .close() it when your program ends (or even AutoCloseable) or add a JVM shutdown hook.
So I have a method to write a string to a file:
public static void saveStringToFile(String path, String string) {
File file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileWriter out = null;
try {
out = new FileWriter(path);
out.write(string);
if (out != null) {
out.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
And my test class with the following setUp method which runs before each test (to delete the testfile before each one):
public static final String TEST_FILE = "somefile.xml";
//...
#Before
public void setUp() throws IOException {
if (MyCustomClass.fileExists(TEST_FILE)) {
new File(TEST_FILE).delete();
}
}
Each of my test tries to write something to the file using the method saveStringToFile(). It succeeds like for a couple of times, but a some random point I finally get the java.io.IOException: Access is denied. Got no idea why this happens - sometimes it occurs in test1, sometimes in test3...
It was working OK, when I was using Java7 FileIO, but I needed to migrate back to Java6...
Are you testing that you are able to create, write to and delete a file, or are you testing what is written to the file?
If the latter, then perhaps you should be mocking/overriding the saveStringToFile( ... ) method and instead focus on verifying that the code you're unit testing actually produces the correct output.
If the former, then I quite agree with #Omaha's suggestion that your test runner is likely running several tests in parallel.
Hope that helps.
There's some problems with the exception handling. The call to out.close() should be within a separate try-catch block inside a finally block. If an exception is thrown when writing to the file, the file is never closed.
I would recommend looking at something like Apache Commons IO which has many useful IO methods like FileUtils.writeStringToFile().
So, probably JUnit wasn't running it parrallel, cause as I suppose It doesn't do it by default.
The problem was in my readfile method:
private String readFile(String path) throws FileNotFoundException {
return (new Scanner(new File(path))).useDelimiter("\\Z").next();
}
To work fine I had to fix
private String readFile(String path) throws FileNotFoundException {
Scanner scanner = (new Scanner(new File(path)));
String s = scanner.useDelimiter("\\Z").next();
scanner.close();
return s;
}
The close() method for Scanner was the key...
Findbugs bugs me about a method which opens two Closeable instances, but I can't understand why.
Source
public static void sourceXmlToBeautifiedXml(File input, File output)
throws TransformerException, IOException, JAXBException {
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output);
try {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
} finally {
try {
fileReader.close();
} finally {
fileWriter.close();
}
}
}
Findbugs analysis
Findbugs tells me
Method [...] may fail to clean up java.io.Reader [...]
and points to the line with FileReader fileReader = ...
Question
Who is wrong: me or Findbugs?
FindBugs is correct: If the FileWriter's constructor throws an exception, the file reader will not be closed. To verify this, try passing an invalid filename for output.
I'd do it as follows:
FileReader fileReader = new FileReader(input);
try {
FileWriter fileWriter = new FileWriter(output);
try {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
} finally {
fileWriter.close();
}
} finally {
fileReader.close();
}
Note that the handling of exception thrown when closing could be improved, since leaving a finally-block by throwing an exception will cause the try-statement to terminate by throwing that exception, swallowing any exception thrown in the try-block, which generally would be more useful for debugging. See duffymo's answer for a simple way on how to avoid this.
Edit: Since Java 7, we can use the try-with-resources statement, which permits correct and concicse handling of these corner cases:
try (
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output)
) {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
}
This may be complicated even for findbugs.
try {
fileReader.close();
} finally {
fileWriter.close();
}
Seems to me you are right.
EDIT : Wow, I thought I will get voted down for saying findbugs can be wrong!
EDIT : Looks like FindBugs is right after all. Good catch meriton.
i'd say it's you.
i'd close both resources in a separate try/catch block. i'd create static methods to help me:
public static void sourceXmlToBeautifiedXml(File input, File output)
throws TransformerException, IOException, JAXBException {
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output);
try {
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
} finally {
close(fileReader);
close(fileWriter);
}
}
// same for reader & writer
public static void close(InputStream s)
{
try
{
if (s != null)
{
s.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
I think findbugs is right.
} finally {
try {
fileReader.close();
} finally {
fileWriter.close();
}
}
In this block you try to close your FileReader. This however can throw an exception and in the nested finally you close the fileWriter. Have you tried closing both readers in the same finally block? What does findbugs say then?
} finally {
try {
fileReader.close();
fileWriter.close();
} finally {
//dunno maybe log that something went wrong.
}
}
Alright, I have been doing the following (variable names have been changed):
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... handle error ...
}
finally
{
if (fis != null)
fis.close();
}
Recently, I started using FindBugs, which suggests that I am not properly closing streams. I decide to see if there's anything that can be done with a finally{} block, and then I see, oh yeah, close() can throw IOException. What are people supposed to do here? The Java libraries throw too many checked exceptions.
For Java 7 and above try-with-resources should be used:
try (InputStream in = new FileInputStream(file)) {
// TODO: work
} catch (IOException e) {
// TODO: handle error
}
If you're stuck on Java 6 or below...
This pattern avoids mucking around with null:
try {
InputStream in = new FileInputStream(file);
try {
// TODO: work
} finally {
in.close();
}
} catch (IOException e) {
// TODO: error handling
}
For a more detail on how to effectively deal with close, read this blog post: Java: how not to make a mess of stream handling. It has more sample code, more depth and covers the pitfalls of wrapping close in a catch block.
Something like the following should do it, up to you whether you throw or swallow the IOException on attempting to close the stream.
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... blah blah blah ...
}
finally
{
try
{
if (fis != null)
fis.close();
}
catch (IOException e)
{
}
}
You could use the try-with-resources feature added JDK7. It was created precisely to deal with this kind of things
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
The documenation says:
The try-with-resources statement ensures that each resource is closed
at the end of the statement.
You could also use a simple static Helper Method:
public static void closeQuietly(InputStream s) {
if (null == s) {
return;
}
try {
s.close();
} catch (IOException ioe) {
//ignore exception
}
}
and use this from your finally block.
Nothing much to add, except for a very minor stylistic suggestion. The canonical example of self documenting code applies in this case - give a descriptive variable name to the ignored IOException that you must catch on close().
So squiddle's answer becomes:
public static void closeQuietly(InputStream s) {
try {
s.close();
} catch (IOException ignored) {
}
}
In most cases, I find it is just better not to catch the IO exceptions, and simply use try-finally:
final InputStream is = ... // (assuming some construction that can't return null)
try {
// process is
...
} finally {
is.close();
}
Except for FileNotFoundException, you generally can't "work around" an IOException. The only thing left to do is report an error, and you will typically handle that further up the call stack, so I find it better to propagate the exception.
Since IOException is a checked exception, you will have to declare that this code (and any of its clients) throws IOException. That might be too noisy, or you might not want to reveal the implementation detail of using IO. In that case, you can wrap the entire block with an exception handler that wraps the IOException in a RuntimeException or an abstract exception type.
Detail: I am aware that the above code swallows any exception from the try block when the close operation in the finally block produces an IOException. I don't think that is a big problem: generally, the exception from the try block will be the same IOException that causes the close to fail (i.e. it is quite rare for IO to work fine and then fail at the point of closing). If this is a concern, it might be worth the trouble to "silence" the close.
The following solution correctly throws an exception if close fails without hiding a possible exception before the close.
try {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
} catch(IOException exc) {
// kernel panic
}
This works because calling close a second time has no effect.
This relies on guava Closeables, but one can write its own closeQuietly method if preferred, as shown by squiddle (see also serg10).
Reporting a close error, in the general case, is important because close might write some final bytes to the stream, e.g. because of buffering. Hence, your user wants to know if it failed, or you probably want to act somehow. Granted, this might not be true in the specific case of a FileInputStream, I don't know (but for reasons already mentioned I think it is better to report a close error if it occurs anyway).
The above code is a bit difficult to grasp because of the structure of the embedded try blocks. It might be considered clearer with two methods, one that throws an IOException and one that catches it. At least that is what I would opt for.
private void work() throws IOException {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
}
public void workAndDealWithException() {
try {
work();
} catch(IOException exc) {
// kernel panic
}
}
Based on http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html (referenced by McDowell).
Hopefully we will get closures in Java some day, and then we will lose lots of the verbosity.
So instead there will be a helper method somwhere in javaIO that you can import, it will probably takes a "Closable" interface and also a block. Inside that helper method the try {closable.close() } catch (IOException ex){ //blah} is defined once and for all, and then you will be able to write
Inputstream s = ....;
withClosable(s) {
//your code here
}
Are you concerned primarily with getting a clean report from FindBugs or with having code that works? These are not necessarily the same thing. Your original code is fine (although I would get rid of the redundant if (fis != null) check since an OutOfMemoryException would have been thrown otherwise). FileInputStream has a finalizer method which will close the stream for you in the unlikely event that you actually receive an IOException in your processing. It's simply not worth the bother of making your code more sophisticated to avoid the extremely unlikely scenario of
you get an IOException and
this happens so often that you start to run into finalizer backlog issues.
Edit: if you are getting so many IOExceptions that you are running into problems with the finalizer queue then you have far far bigger fish to fry! This is about getting a sense of perspective.