JavaDoc for InputStreamReader doesn't say anything about closing the underlying InputStream:
https://docs.oracle.com/javase/8/docs/api/java/io/InputStreamReader.html#close--
Description copied from class: Reader
Closes the stream and releases any system resources associated with it. Once the stream has been closed, further read(), ready(), mark(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.
Does closing an InputStreamReader also close the underlying InputStream?
UPDATE In:
InputStreamReader istream = new InputStreamReader(conn.getInputStream(), "UTF-8")
istream.close();
Do I need to close conn.getInputStream()?
InputStreamReader implementation direct close call to StreamDecoder which is a native class.
As other answers and comments said, the answer is yes, it does close the InputStream. You can see for yourself with the following code:
InputStream is = new FileInputStream("D:\\a.txt");
Reader r = new InputStreamReader(is);
r.close();
is.read(); // throws exception: stream is closed.
Therefore, if you close the Reader, you don't need to also close the InputStream. However, I guess you are using try-with-resources everywhere (aren't you? ;) ) and the InputStream as well as the Reader will both be closed at the end of the try block. That doesn't matter, because an InputStream can be closed multiple times; it's a no-op if the stream is already closed.
If you want to avoid closing the InputStream, you can write a simple wrapper that does nothing when it is closed:
class UncloseableInputStream extends FilterInputStream {
public UncloseableInputStream(InputStream is) {
super(is);
}
public void close() {
// Do nothing.
}
}
InputStream is = new FileInputStream("D:\\a.txt");
Reader r = new InputStreamReader(new UncloseableInputStream(is));
r.close();
is.read(); // still works despite closing the reader.
It depends on stream implementation. InputStream is just an "interface" in terms of close(). InputStreamReader will not close an interface. It will close the underlying data resource (like file descriptor) if it is. It will do nothing if close is override and empty in an implementation.
In OpenJdk StreamDecoder has a method
void implClose() throws IOException {
if(this.ch != null) {
this.ch.close();
} else {
this.in.close();
}
}
this.in is a InputStream from decoder constructor:
StreamDecoder(InputStream var1, Object var2, CharsetDecoder var3) {
...
if(this.ch == null) {
this.in = var1;
...
}
...
}
Here are examples of closing actions. ByteArrayInputStream:
Closing a ByteArrayInputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.
public void close() throws IOException {
}
FileInputStream differes:
Closes this file input stream and releases any system resources associated with the stream. If this stream has an associated channel then the channel is closed as well. After you closed the underlying instance it doesn't matter which interfaces were using it, it will be closed.
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
if (channel != null) {
channel.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
close0();
}
});
}
Related
To produce two diferent files to a ZipStream I am using two methods receiving an outputStream something like this:
private void produceFileA (OutputStream stream){
final PrintStream printer = new PrintStream (stream);
......
}
private void produceFileB (OutputStream stream) {
final PrintStream printer = new PrintStream (stream);
.....
}
client:
private void produceZip () {
try (ZipOutputStream zipStream = new ....) {
...
produceFileA (zipStream);
...
produceFileB (zipStream);
....
}
}
both will receive the same ZipOutputStream so I dont see how I can close the PrintStream created here if produceFileA closes it the produceFileB will not work anymore since it will receive a closed stream.. it is ok if I let them unclosed after finishing the methods call? (the underlying zipStream is closed by the client of these methods)
I am trying to be sure my PrintStreams dont leak any resource.
I am planning a function that creates and returns an InputStream that in turn reads from another InputStream because the initialization of that InputStream is not trivial and I would like to use it in multiple places. Consider this simple example:
private static InputStream openStream() throws IOException {
Path path = Paths.get("/etc/passwd");
InputStream inputStream = Files.newInputStream(path);
return new BufferedInputStream(inputStream);
}
I will use this function as follows:
public static void main(String[] args) {
try (InputStream stream = openStream()) {
byte[] buffer = new byte[1024];
int numBytes;
while ((numBytes = stream.read(buffer, 0, buffer.length)) > 0) {
System.out.printf("Just read %d bytes from stream!%n", numBytes);
}
} catch (IOException e) {
e.printStackTrace();
}
}
However, I am concerned that closing the BufferedInputStream in this example will not close the InputStream inside it. Will this lead to orphaned file handles and memory leaks if called multiple times? What is a better solution for this?
A simple solution I could think of is to define a closable container class and put both input streams into that class. When calling close(), this class would simply close all its open handles.
class StreamContainer implements Closeable {
private final InputStream[] inputStreams;
public StreamContainer(InputStream... inputStreams) {
this.inputStreams = inputStreams;
}
#Override
public void close() throws IOException {
for (InputStream inputStream : this.inputStreams) {
inputStream.close();
}
}
}
But I suppose, there might be a better solution, built-in mechanic or development pattern. Or maybe these constructs should be avoided?
In this cases you should read the code source of the BufferedInputStream, this is the close definition
public void close() throws IOException {
while(true) {
byte[] buffer;
if ((buffer = this.buf) != null) {
if (!U.compareAndSetObject(this, BUF_OFFSET, buffer, (Object)null)) {
continue;
}
InputStream input = this.in;
this.in = null;
if (input != null) {
input.close();
}
return;
}
return;
}
}
As you can see when closing the BufferedInputStream, the underlying input stream is closed as well.
And this is the documentation of close:
public void close() throws IOException
Closes this input stream and releases any system resources associated with the stream. Once the
stream has been closed, further read(), available(), reset(), or
skip() invocations will throw an IOException. Closing a previously
closed stream has no effect.
I am using a BufferedWriter to write in a File. All the nested streams of the BufferedWriter (FileOutputStream, GzipOutputStream, OuputStreamWriter, ...) should be automatically closed if I close the BufferedWriter. If all of the streams have been instantiated then closing only the outermost is just fine.
The documentation on Closeable interface states that close method:
Closes this stream and releases any system resources associated with
it.
So, I am wondering why I cannot find a out.close(); in the source code of the java.io.BufferedWriter :
// Java 11.0.12_7 source code. Line 262
public void close() throws IOException {
synchronized (lock) {
if (out == null) {
return;
}
try (Writer w = out) {
flushBuffer();
// Why don't we have a out.close() here ?
} finally {
out = null;
cb = null;
}
}
}
How the out Writer is it closed ?
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.
OutputStream fos;
OutputStream bos;
OutputStream zos;
try {
fos = new FileOutputStream(anyFile);
bos = new BufferedOutputStream(fos);
zos = new ZipOutputStream(bos);
} finally {
if (zos != null) {
zos.close(); // + exception handling
}
}
Does closing zos automatically closes bos and fos too, or do I need to close them manually?
Yes, it does. Its Javadoc says:
Closes the ZIP output stream as well as the stream being filtered.
Also, the Javadoc for BufferedOutputStream says:
Closes this output stream and releases any system resources associated with the stream.
The close method of FilterOutputStream calls its flush method, and then calls the close method of its underlying output stream.
So when you close your ZipOutputStream, it will close your BufferedOutputStream, which will in turn close your FileOutputStream.
Yes.
ZipOutputStream.close() method is specified by Closeable.close() which:
Closes this stream and releases any system resources associated with
it.
The same applies to BufferedOutputStream.close(), a method inherited from FilterOutputStream.
Closing the wrapper stream automatically closes the inner stream.
So, in your case you only need to close ZipOutputStream. Closing a stream twice does not throw an exception hence closing an inner stream again (although unnecessary) works as well.
Here's what happens when you instantiate a ZipOutputStream
public ZipOutputStream(OutputStream out) {
this.out = out; // BufferedOutputStream reference saved
}
Here's the implementation of ZipOutputStream.close()
public void close() throws IOException {
try {
flush();
} catch (IOException ignored) {
}
out.close(); // BufferedOutputStream being closed
}
Similarly, BufferedOutputStream automatically closes the FileOutputStream through its inherited FilterOutputStream#close() which has been implemented as:
public void close() throws IOException {
try {
flush();
} catch (IOException ignored) {
}
out.close(); // FileOutputStream being closed
}
Yes it does. but strangely when i was running the fortify scan with find bug enabled it catches all these kind of wrapped and unclosed streams as high priority items to be fixed. Not sure why they do so