Do I need to close an InputStream in Java? - java

My code is:
InputStream confFile=classLoader.getResourceAsStream("myconffile.properties");
In docs:
The close method of InputStream does nothing.
Does it mean that I don't need close InputStream?

You do need to close the input Stream, because the stream returned by the method you mention is actually FileInputStream or some other subclass of InputStream that holds a handle for a file. If you do not close this stream you have resource leakage.

No, it does not mean that - because InputStream is an abstract class, and getResourceAsStream() returns a concrete subclass whose close() method does something - most importantly free a file handle.

Related

try-with-resources where to wrap stream with InputStreamReader?

I may be overthinking this, but I just wrote the code:
try (InputStream in = ModelCodeGenerator.class.getClassLoader().getResourceAsStream("/model.java.txt"))
{
modelTemplate = new SimpleTemplate(CharStreams.toString(new InputStreamReader(in, "ascii")));
}
Which means the InputStreamReader is never closed (but in this case we know its close method just closes the underlying InputStream.)
One could write it as:
try (InputStreamReader reader = new InputStreamReader(...))
But this seems worse. If InputStreamReader throws for some reason, the InputStream won't ever be closed, right? This is a common problem in C++ with constructors that call other constructors. Exceptions can cause memory/resource leaks.
Is there a best practice here?
Which means the InputStreamReader is never closed
Eh? In your code it is... And it will certainly handle the .close() of your resource stream as well. See below for more details...
As #SotiriosDelimanolis mentions however you can declare more than one resource in the "resource block" of a try-with-resources statement.
You have another problem here: .getResourceAsStream() can return null; you may therefore have an NPE.
I'd do this if I were you:
final URL url = ModelCodeGenerator.class.getClassLoader()
.getResource("/model.java.txt");
if (url == null)
throw new IOException("resource not found");
try (
final InputStream in = url.openStream();
final Reader reader = new InputStreamReader(in, someCharsetOrDecoder);
) {
// manipulate resources
}
There is a very important point to consider however...
Closeable does extend AutoCloseable, yes; in fact it only differs, "signature wise", by the exception thrown (IOException vs Exception). But there is a fundamental difference in behavior.
From the javadoc of AutoCloseable's .close() (emphasis mine):
Note that unlike the close method of Closeable, this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once. However, implementers of this interface are strongly encouraged to make their close methods idempotent.
And indeed, the javadoc of Closeable is clear about this:
Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
You have two very important points:
by contract, a Closeable also takes care of all resources associated with it; so, if you close a BufferedReader which wraps a Reader which wraps an InputStream, all three are closed;
should you call .close() more than once, there is no further side effect.
This also means, of course, that you can choose the paranoid option and keep a reference to all Closeable resources and close them all; beware however if you have AutoCloseable resources into the mix which are not Closeable!
But this seems worse. If InputStreamReader throws for some reason, the
InputStream won't ever be closed, right?
That's right (although unlikely, the InputStreamReader constructor doesn't really do much).
The try-with-resources lets you declare as many resources as you'd like. Declare one for the wrapped resource, and another for the InputStreamReader.
try (InputStream in = ModelCodeGenerator.class
.getClassLoader()
.getResourceAsStream("/model.java.txt");
InputStreamReader reader = new InputStreamReader(in)) {...}
Note that getResourceAsStream can potentially return null, which would cause the InputStreamReader constructor to throw a NullPointerException. If you want to deal with that differently, adapt how you retrieve the resource that's meant to be wrapped.
The tutorial linked above presents this example
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
with the explanation
In this example, the try-with-resources statement contains two
declarations that are separated by a semicolon: ZipFile and
BufferedWriter. When the block of code that directly follows it
terminates, either normally or because of an exception, the close
methods of the BufferedWriter and ZipFile objects are automatically
called in this order. Note that the close methods of resources are
called in the opposite order of their creation.

Close Encapsulating Writers/Streams for ServletOutputStream

I know it has been the point of many previous questions to close or not to close a ServletOutputStream like here: Should I close the servlet outputstream? or here: Should one call .close() on HttpServletResponse.getOutputStream()/.getWriter()? or with another focus here: Do I need to flush the servlet outputstream?
The general consensus seems to be not to close it because you are not owning it in a more strict sense. (The HttpServletResponse owns it.)
But what about e.g. these constructs:
PrintWriter out = new PrintWriter( new OutputStreamWriter( resp.getOutputStream(), MY.ENCODING ) );
Now I'm clearly the owner of the PrintWriter which has some additional buffers which at least needs to get flushed (and which are flushed e.g. by closing it).
What is the general consensus here? Do I need to close the PrintWriter (or any other such construct as for this matter.)?
EDIT: There are valid arguments for closing the stream, too. Notable e.g. not wanting something else writing on the stream. And meanwhile we have with try-with-resource constructs which might change the picture. See my other question here: Eclipse complaining over resource leak when not closing ServletOutputStream
This might change nothing (and my general feeling is to not close the stream, too) but try-with-resource above all literally screams for code like:
try( Something out = new Something( resp.getOutputStream() ) ){
out.print( "Foo" );
}
instead of
Something out;
try {
out = new Something( resp.getOutputStream() );
out.print( "Foo" )
} finally {
if( out != null && out.isUnFlushedWhatever() ) out.flush();
}
The OutputStream is something you're not creating, you just query a reference to it with ServletResponse.getOutputStream(). Therefore if you put something around it (e.g. OutputStreamWriter or ZipOutputStream) the wrapper stream or writer will just write to it.
It is implementation dependant whether closing a wrapper stream or writer closes the underlying stream, so you should not close that. But since in most of the cases the wrappers only use the underlying stream to write bytes, it is more than enough to flush the wrapper.
In cases where the wrapper needs some finalizing, it should be (and generally is) the wrapper's responsibility to provide this finalizing functionality in a separate method. For example ZipOutputStream provides a finish() method which finishes writing the contents of the ZIP output stream without closing the underlying stream.
Summarizing:
You should not close the wrapper, but check if it provides some finalizing method without closing the underlying stream, which you should obviously call.

ObjectInputStream available() method doesn't work as expected (Java)

I've been trying to figure out why a method I've written to read objects from a file didn't work and realized that the available() method of ObjectInputStream gave 0 even though the file wasn't fully read.
The method did work after I've used the FileInputStream available() method instead to determine the EOF and it worked!
Why doesn't the method work for ObjectInputStram while it works for FileInputStream?
Here's the code:
public static void getArrFromFile() throws IOException, ClassNotFoundException {
Product p;
FileInputStream in= new FileInputStream(fName);
ObjectInputStream input= new ObjectInputStream(in);
while(in.available()>0){
p=(Product)input.readObject();
if (p.getPrice()>3000)
System.out.println(p);
}
input.close();
P.S-
I've read that I should use the EOF exception instead of available() for this, but I just wanna know why this doesn't work.
Thanks a lot!!!
Because, as the javadoc tells, available() returns an estimation of the number of bytes that can be read without blocking. The base InputStream implementation always returns 0, because this is a valid estimation. But whatever it returns, the fact that it returns 0 doesn't mean that there is nothing to read anymore. Only that the stream can't guarantee that at least one byte can be read without blocking.
Although this is not documented clearly I have realized from experience that it has to do with dynamic data. If your class only contains statically typed data, then available() is able to estimate the size. If there are dynamic data in your object, like lists etc, then it is not possible to make that estimation.
The available() method just tells how many bytes can be read without blocking. It's not very useful in regular code, but people see the name and erroneously think it does something else.
So in short: don't use available(), it's not the right method to use. Streams indicate ending differently, such as returning -1 or in ObjectInputStream's case, throwing an EOFException.
I found some trick! If you still want to use .available() to read all objects to the end, you can add an integer (ex: out.writeInt(0)) before adding each Object (ex: out.writeObject(obj)) when you write to the file and also read integer before reading each Object. So .available() can read byte left on file and won't be crash! Hope it helps you!
Use available function of InputStream instead of ObjectInputStream. Then if there is any data, get them as an object.
Something like:
if(inputStreamObject.available() > 0){
Object anyName = objectInputStreamObject.readObject();
}
You can get the inputStreamObject directly from the Socket.
I used it and the problem solved.

Is it possible to use a stream more than once?

In short I need to do two things with one stream.
I need to pass a stream through a method to see if the bytes of that stream are of a particular type.
I need to create a new class using that stream once that check is completed.
I'm very new to streams and I know that they are "one way streets." So I think I have a bad design in my code or something if I find myself needing to reuse a stream.
Here is a snippit of the logic:
byte[] header = new byte[1024];
//reads entire array or until EOF whichever is first
bis.mark(header.length);
bis.read(header);
if(isFileType(header)) {
bis.reset();
_data.put(fileName, new MyClass(bis)); // Stream is now closed...
methodForFinalBytes(bis);
} else {
// Do other stuff;
}
It depends entirely on whether the InputStream implementation supports mark(). See http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#markSupported(). Calling reset() on a stream that doesn't support mark() may throw an exception.
BufferedInputStream and ByteArrayInputStream support mark(), but others don't.
Generally, you can't reset an InputStream to get back to the start. There are, however the mark() / reset() methods, which make a stream remember the current position and you can rewind the stream to the marked position with reset().
Problem is, they are optional and may not be supported by the particular stream class in use. BufferedInputStream does support mark() / reset() (although within buffer limits). You can wrap your InputStream in a BufferedInputStream, immediately mark() and then run your detection code (but make sure it does not read ahead further than the buffer size, you can specify the buffer size in the BufferedInputStream constrcutor). Then call reset() and really read the stream.
EDIT: If you use ByteArrayInputStream anyway, that one supports mark/reset over its entire length (naturally).

Java Detect Closed Stream

I have a general socket implementation consisting of an OutputStream and an InputStream.
After I do some work, I am closing the OutputStream.
When this is done, my InputStream's read() method returns -1 for an infinite amount of time, instead of throwing an exception like I had anticipated.
I am now unsure of the safest route to take, so I have a few of questions:
Am I safe to assume that -1 is only
returned when the stream is closed?
Is there no way to recreate the IO
exception that occurs when the
connection is forcefully broken?
Should I send a packet that will tell my InputStream that it should close instead of the previous two methods?
Thanks!
The -1 is the expected behavior at the end of a stream. See InputStream.read():
Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
You should still catch IOException for unexpected events of course.
Am I safe to assume that -1 is only returned when the stream is closed?
Yes.
You should not assume things like this. You should read the javadoc and implement according how the API is specified to behave. Especially if you want your code to be robust (or "safe" as you put it.)
Having said that, this is more or less what the javadoc says in this case. (One could quibble that EOF and "stream has been closed" don't necessarily mean the same thing ... and that closing the stream by calling InputStream.close() or Socket.close() locally will have a different effect. However, neither of these are directly relevant to your use-case.)
Is there no way to recreate the IO exception that occurs when the connection is forcefully broken?
No. For a start, no exception is normally thrown in the first place, so there is typically nothing to "recreate". Second the information in the original exception (if there ever was one) is gone.
Should I send a packet that will tell my InputStream that it should close instead of the previous two methods?
No. The best method is to test the result of the read call. You need to test it anyway, since you cannot assume that the read(byte[]) method (or whatever) will have returned the number of bytes you actually asked for.
I suppose that throwing an application specific exception would be OK under some circumstances.
But remember the general principle that exceptions should not be used for normal flow control.
One of the other answers suggests creating a proxy InputStream that throws some exception instead of returning -1.
IMO, that is a bad idea. You end up with a proxy class that claims to be an InputStream, but violates the contract of the read methods. That could lead to trouble if the proxy was passed to something that expected a properly implemented InputStream.
Second, InputStream is an abstract class not an interface, so Java's dynamic proxy mechanism won't work. (For example, the newProxyInstance method requires a list of interfaces, not classes.)
According to the InputStream javadoc, read() returns:
the next byte of data, or -1 if the end of the stream is reached.
So you are safe to assume that and it's better to use what's specified in the API than try and recreate an exception because exceptions thrown could be implementation-dependent.
Also, closing the Outputs Stream in a socket closes the socket itself.
This is what the JavaDoc for Socket says:
public OutputStream getOutputStream()
throws IOException
Returns an output stream for this socket.
If this socket has an associated channel then the resulting output
stream delegates all of its operations
to the channel. If the channel is in
non-blocking mode then the output
stream's write operations will throw
an IllegalBlockingModeException.
Closing the returned OutputStream will close the associated socket.
Returns:
an output stream for writing bytes to this socket.
Throws:
IOException - if an I/O error occurs when creating the output stream
or if the socket is not connected.
Not sure that this is what you actually want to do.
Is there no way to recreate the IO exception that occurs when the connection is forcefully broken?
I'll answer this one. InputStream is only an interface. If you really want implementation to throw an exception on EOF, provide your own small wrapper, override read()s and throw an exception on -1 result.
The easiest (least coding) way would be to use a Dynamic Proxy:
InputStream pxy = (InputStream) java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
new Class[]{ InputStream.class },
new ThrowOnEOFProxy(obj));
where ThrowOnEOFProxy would check the method name, call it and if result is -1, throw IOException("EOF").

Categories

Resources