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
Related
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.
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();
}
});
}
I've heard that calling 'socket.close()' automatically closes it's streams.
Would:
public void close() {
try {
socket.close();
}catch(IOException e) { }
}
Have the same effect as:
public void close() {
try {
outputstream.close();
inputstream.close();
socket.close();
}catch(IOException e) { }
}
If your goal was to completely close the socket?
Closing a socket will also close the socket's InputStream and OutputStream:
http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#close()
Yes, closing the input or output stream or the socket closes both streams and the socket.
However you shouldn't close the socket, you should close the outermost OutputStream or Writer you have wrapped around its output stream, so it gets flushed. Only you can do that. The socket can only close its output stream, not what you've wrapped around it.
You should do this is you have a buffered output stream. This will flush any data which has not been sent yet.
Otherwise, closing the socket will close the streams so it is redundant.
I using FileReader to read and FileWriter to a file. I am seeing that reading is successful (by printing to console) but writing does not happen.
here is the code:
public class ReadingIO {
public static void main(String[] args){
try {
processfile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void processfile() throws IOException{
BufferedReader fi = new BufferedReader(new FileReader("words.txt"));
Writer out = new BufferedWriter(new FileWriter("testwrite.txt"));
String b;
while ((b=fi.readLine())!=null){
System.out.println(b);
out.write(b);
}
}
}
If I use FileInputStream and FileOutputStream it works. I want to know why FileWriter fails, not alternative ways to accomplish this.
You need to call flush() while using Writer.
But not needed while FileOutputStream
Close calls flush on the stream, so flush is not needed if you want to close the stream.
You need to call out.flush() when you are done.
Add following lines after while loop.
out.close();
This method will cal flush() method automatically to write data to file which is still buffered, then close the stream.