Java: Why does an unclosed stream not throw an exception? - java

I wanted to write to a property file. But it silently never worked. Just from the code behavior I could not notice it. I always had to open the properties file and look if the value changed. But it never did. So actually I would expect to get an exception . The problem seemed to be that I did not close the InputStream before opening the OutputStream. But I never got to know that. It cost me 3 days because I would expect either OutputStream or store function to give me some feedback. Have a look at the code.
File file = ResourceUtils.getFile("classpath:First.properties");
FileInputStream in = new FileInputStream(file);
Properties props = new Properties();
props.load(in);
System.out.println(props.getProperty("country"));
in.close(); // This I always forgot
FileOutputStream out = new FileOutputStream(file);
props.setProperty("country", "germany");
props.store(out, null);
System.out.println(props.getProperty("country"));
out.close();

As for the actual question "why does it not throw an exception", it's because there are cases you want the Stream to remain open.
class FileWriteSample implements Closeable {
FileOutputStream writeTo;
public FileWriteSample(String filename) throws IOException {
writeTo = new FileOutputStream(filename);
// should we expect an Exception here because we don't close the Stream?
// we're planning to use it later on
}
public void write(String s) {
// write to stream
}
public void close() throws IOException {
writeTo.close();
}
}

A forgotten close() statement cannot cause an exception. From the perspective of your stream everything is okay. It just didn't wrote to its destination yet. Why should it? Even when the whole program terminates there is no guaranty that the stream closes and writes its internal buffers out.[1]
You always have to call flush() or close() actively. The underlying implementation will then perform the actual write operation.
This mistake is so common that there is an extra Java-Feature to handle it. It is called try-with-resources and prevents programmers from the evil consequences of missing close() statements.
Example:
//use try-with-resources on out
private void saveProperties(Properties properties, String path) {
try(PrintStream out = new PrintStream(new FileOutputStream(path))) {
printProperties(properties,out);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// you can pass System.out as well to print to console
private void printProperties(Properties properties, PrintStream out) {
try {
properties.store(out, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//properties.load leaves the stream open, so you have to use try-with-resources
private Properties readProperties(String path) {
try (FileInputStream in = new FileInputStream(path)) {
Properties properties = new Properties();
properties.load(in);
return properties;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Related posts on Java Properties:
Read properties from outside of a jar: https://stackoverflow.com/a/54766296/1485527
Sorted print of properties: https://stackoverflow.com/a/54781548/1485527
Related posts on Java Streams:
Closing Streams in Java
[1] See: Josh Bloch, Effective Java,(2nd ed.), Page 27.
Avoid finalizers.[...] It is entirely possible, even likely, that a program terminates without executing finalizers on some objects that are no longer reachable.

Related

how to return FileInputStream ?? in java [duplicate]

This question already has answers here:
Java return value (in try/catch clause)
(6 answers)
Closed 2 years ago.
package asasaSASA;
import java.io.*;
class FileInputTest {
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis; // I HAVE RETURN fis
}
catch (FileNotFoundException e) {
System.out.println("에러는"+e);
}
}
public static void main(String args[]) {
FileInputStream fis1 = null;
String fileName = "foo.bar";
System.out.println("main: Starting " + FileInputTest.class.getName()
+ " with file name = " + fileName);
fis1 = f1(fileName);
System.out.println("main: " + FileInputTest.class.getName() + " ended");
}
}
I want to make this code run but it said
This method must return a result of type FileInputStream
I can't understand because I made return fis. Why does it say that you have to return? I already returned it!
FileInputStream fis = new FileInputStream(fileName);
If the above line throws a FileNotFoundException then the next line of your code that will be executed is
System.out.println("에러는"+e);
which means it bypasses your return statement and that's why you are getting the compiler error.
There are many different ways to fix the compiler error and the other answers explain the different ways. I'm just answering your question, namely
Why does it say that you have to return?
I hope you understand now why you are wrong when you say
I already returned it!
Your exception handling is the problem. It's common, but bad code style: Whenever you catch an exception, the right move is to either deal with that exception, or, to ensure that you (re)throw some exception.
Log it, or print it? That is not handling an exception.
In this case, 'file not found' is not something you can be expected to handle; not unless you expand on what f1 is supposed to do (tip: Methods should be a bit more descriptive than that). Thus, throwing something is fair game. Furthermore, the very definition of f1 (presumably; that name is not particular enlightening and the method has no documentation) suggests that 'open this file' is a fundamental aspect of it, and therefore, throwing a FileNotFoundException is fair as well.
Thus:
Best solution
public static FileInputStream f1(String fileName) throws IOException {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
}
public static void main(String[] args) throws Exception {
String fileName = "foo.bar";
System.out.println("main: Starting " + FileInputTest.class.getName()
+ " with file name = " + fileName);
try (InputStream in = f1(fileName)) {
// you must close any resources you open using a try-with-resources
// construct; you did not do that in your code, I fixed this.
}
}
NB: your psv main can (and generally should!) be declared to throws Exception.
Alternate take
This one works in any scenario where you cannot throws the exception, or if adding that the signature makes no sense because it reflects an implementation detail and not an inherent aspect of what the method is trying to do:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch (IOException e) {
throw new RuntimeException("Unhandled", e);
}
}
Naturally, this is only appropriate for situations where you really don't expect that exception to occur under normal circumstances. Otherwise, either throw that exception onwards or make your own exception type and throw that instead of RuntimeException.
If you just need a ¯\(ツ)/¯ I don't really know what this means, I just want to move on and get rid of these exceptions solution: throw new RuntimeException("Uncaught", e); is correct; e.printStackTrace(); is incorrect. Update your IDE's templates.
Your method throws a checked exception which must be handled either inside of the method, or outside. Checked exception are to indicate that a problem may occur and you need to implement something to handle this scenario. Here we are worried that the file does not exist.
You have three Choices:
Return and handle value for not existing file (no exception is thrown here). So either return null, then check in main() that inputStream is not null, or return Optional<>, which is a JDK8 way to handle such scenarios.
Example:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch(FileNotFoundException e) {
System.out.println("Error "+e);
return null; // in case of not existing file
}
}
Wrap your checked FileNotFoundException into a custom RuntimeException. This will solve your problem with compile error, but may cause problems in the future if you will not catch this exception somewhere.
Example:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch(FileNotFoundException e) {
System.out.println("Error "+e);
throw new RuntimeException(e);
}
}
Instead of try-catch add this exception to your method signature:
Example:
public static FileInputStream f1(String fileName) throws FileNotFoundException{
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
}
But if you declare a checked exception in a method at some point you will have to catch it and handle.
Option 3 is most desired.

Java: Writing to a log file from a server

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.

Java: Does nu.xom.Builder properly close Files?

I am using nu.xom.* for my project, link found at http://www.xom.nu/. My question is about the following part of my code:
private void open() {
builder = new Builder();
try {
document = builder.build(file);
} catch (ParsingException | IOException ex) {
Logger.getLogger(InvoiceData.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have some unwanted file locks in my program and am practically checking all places where I open a file. Now it struck me here that builder.build(File file) does implement Closeable, so I myself am not sure here whether it closes the file properly or not.
Can anyone shed some light on this?
Regards.
Fortunately the XOM library is open source, so you can take a look at the source code of nu.xom.Builder.build(File):
public Document build(File in)
throws ParsingException, ValidityException, IOException {
InputStream fin = new FileInputStream(in);
// [...]
String base = url.toString();
try {
Document doc = build(fin, base);
return doc;
}
finally {
fin.close();
}
}
So you pass a File instance to the build() method and inside this method a FileInputStream is opened and closed at the end.
There is a part after new FileInputStream(in) which is not enclosed by a try block. If this code throws an unchecked exception it is possible that the input stream isn't closed. But if you don't catch an exception then you can be sure, that the input stream is closed properly.

Preferred way to clean-up resources in Java 1.6

I regularly see this style of resource clean-up:
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} finally {
if (in != null) {
in.close();
}
}
I have always used the following style:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
But am I missing something? Is there an advantage to the former that I'm not seeing?
I suspect its to avoid having two nested try/catch blocks instead of one.
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} catch(IOException ioe) {
// handle exception.
} finally {
IOUtils.closeQuietly(in);
}
The second case is incomplete.
try {
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
} catch(IOException e) {
// handle exception
}
If you have multiple files, this could get really messy.
Suppose that in the first example you have some other code before defining in that gets you out of the try block. If you get to the finally without in been defined you will get a NullPointerException when trying to close it. So you will have to make the check to avoid errors like that.
This is very simple example, And may not create a problem as you are creating InputStream in same bloke. But if InputStream is closed because of some Exception or other fault, in that case your code will fail, So its always better to check if InputStream is available
The second one will not compile since the constructor of FileInputStream can throw a FileNotFoundException, thus you'd need an extra try-catch block, unless of course, the method itself throws it.
Another common idiom is to write a closeQuietly() method to avoid having to write the if (is != null) check all over your finally blocks. This is what Apache Common's IOUtils does:
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
}
} catch (IOException ioe) {
// ignore
}
}
Also note that since Java 7, you can use the following:
try (InputStream is = new FileInputStream(file)) {
} catch (final FileNotFoundException | IOException ex) {
}
The null check here for the InputStream is necessary as it is possible that the variable might not be assigned. In this case a NullPointerException would be thrown when attempting to close it when calling:
in.close();
In the 2nd block outside of the try/catch block:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
You can easily encounter other exceptions before entering the block and the InputStream is never closed.
Lets say you need to open not one, but two files. You would do
final InputStream in = new FileInputStream(file1);
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
in.close();
}
If the out fails to open, you will get an exception and because it's out of the try block in won't be closed in the finally block.
In the other method:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
if (out != null) out.close();
if (in != null) in.close();
}
If out fails to open, you will go to the finally block and close both streams. If in fails to open, you will go to the finally block, and free only in - because out==null.
edit
As the aetheria mentioned, that code wouldn't work because close() throws exception in Java. It can easily be fixed by putting each resource release in it's own try-catch block:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
try{ out.close(); }catch(Exception e){}
try{ in.close(); }catch(Exception e){}
}
I ditched the null checking - if in or out is null, it'll throw a NullPointerException that will be ignored. And the reason I ignore close exceptions is that disposal methods shouldn't throw exceptions in the first place. If handling closing exceptions is required, you can always close the streams again, after the finally block. That way, any stream that can be closed will be closed already(so you wouldn't have to worry about it), and you can handle any exceptions from close more elegantly.
Now, aetheria also suggested to put a separate try-finally block for each resource that would look like this:
final InputStream in = new FileInputStream(file1);
try {
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
}
} finally {
in.close();
}
This works, but even with only two resources, it's much less elegant, as it splits the allocations and releasing code, making it harder to keep track of it(in my opinion, at least).

Closing a Java FileInputStream

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.

Categories