Here is a line reading a file into a List:
List<String> lines =
new BufferedReader(
new InputStreamReader(classLoader.getResourceAsStream(fileName)))
.lines()
.collect(Collectors.toList());
Is this correct or should I assign the BufferedReader to a variable to be able to close it later?
You should always close your resources. Closing may not be a big problem for small programs which only use a couple of files quickly, since most mature OSes will close the files for you when the process completes. However, there are usually limits on how many files you can have open at one time. It is good to be tidy, so that you don't hit those limits when you start writing bigger programs. There are also other types of resources, like network and serial ports, which you may want to let others use once your program is done with them, even if it is still running.
An alternative to closing the file manually is using try-with-resources syntax, which ensures that the file will be closed properly even in case of an error:
List<String> lines;
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(classLoader.getResourceAsStream(fileName)))) {
lines = reader.lines().collect(Collectors.toList());
}
Well, in your concrete example, the stream opened by
classLoader.getResourceAsStream(fileName)
is never closed. This stream must be closed - it is most likely a file handle in the local system. You can close it by closing the BufferedReader, which closes the wrapped InputStreamReader, which closes the underlying InputStream. You could instead also store a reference to the original InputStream and only close this.
Please also have a look into try-with-resources, this could potentially make things easier for you here.
I stand corrected
From documentation:
Streams have a close() method and implement AutoCloseable interface, but nearly all stream instances do not actually need to be closed after use.
Generally, only streams whose source is an IO channel, for example a BufferedReader.lines will require closing.
Most streams are backed by collections, arrays, or generating functions, which require no special resource management. If a stream does require closing, it can be declared as a resource in a try-with-resources statement.
Related
I'm currently writing a program that communicates with a server using TCP sockets. Part of that requires sending information back and forth through several methods. However, I do not want to open up a new socket connection for each request, but I can't guarantee the number or the order of the requests. In order to handle this, I simply keep one socket instance that gets reused a lot.
However, in order to read the data I use BufferedReader wrapper classes. Because I reuse the same socket, I can't call close() on the reader, or I'll close the socket stream as well.
Do I need to call close() on the BufferedReader if I don't want to close the underlying stream? Will I cause a memory leak by not doing this? If I do need to call close() how can I return the memory without closing the socket's stream?
Note: I will close the underlying stream at program termination, this question isn't about that.
Don't close the BufferedReade. More important, don't discard the BufferedReader; instead, pass it around rather than the SocketInputStream.
A BufferedReader, as its name implies, has an internal buffer. When you read from it, it tries to fill that buffer from the underlying Reader. Which means that, if you discard it, those bytes are gone.
And now some unasked advice:
Do you really want to use a Reader? Most communication protocols are better implemented using a DataInputStream/DataOutputStream. With a Reader you're limited to character data (and in the case of BR, lines of character data).
Are you paying attention to encoding? The correct way to construct a Reader on top of an InputStream is to use the two-argument variant of InputStreamReader: new InputStreamReader(in, "UTF-8") (you can use an encoding other than UTF-8, but have a good reason).
It's generally better to use a BufferedInputStream rather than a BufferedReader, because the translation from stream to reader may involve multiple reads. If you want readLine(), you can always use both.
Be sure to close the socket in either a finally or try-with-resources. See this for more info.
System.in is the "standard" input stream which supplies user input data. Once closed, this stream can not be re-opened. One such example is in the case of using a scanner to read the user input as follows:
public class Test {
public static void main(String[] args) {
boolean finished;
do {
Scanner inputScanner = new Scanner(System.in);
finished = inputScanner.hasNext("exit");
boolean validNumber = inputScanner.hasNextDouble();
if (validNumber) {
double number = inputScanner.nextDouble();
System.out.print(number);
} else if (!finished) {
System.out.println("Please try again.");
}
inputScanner.close();
} while (!finished);
}
}
In this example, an instance of type Scanner is created and used to read a series of numbers from the user (please ignore other details with this code which go beyond the scope of this example, I know the scanner should be created and closed outside the loop). After a number is retrieved from user input, the instance of this Scanner (i.e., the input stream) is closed. However, when another number is requested from user, and new instance is created, the input stream cannot be opened again. In case of this example, it creates a infinite loop.
The question is: why is not possible to reopen a closed stream?
why is not possible to reopen a closed stream in Java?
That's simply the nature of the underlying operating system constructs that Java streams represent. A stream is essentially a data conduit. Once you close it, it no longer exists. You may be able to create a new one between the same endpoints, but that yields a fundamentally different stream. We could go into implementation considerations such as buffering and stream positioning, but those are really side issues.
You also asked specifically about the standard streams. These are some of the cases that you cannot recreate. The operating system provides each process with its set of standard streams. Once they are closed, there is no way to obtain equivalents. You can put different streams in their place, but you cannot connect them to the original endpoints.
When you close the standard input stream:
If your input was being provided by a pipe, the other end of the pipe is notified. It will close its end and stop sending data. There is no way to tell it you made a mistake and it should start sending again;
If your input was being provided by a file, the OS drops its reference to the file and completely forgets that you were using it. There is just no way provided for you to reopen standard input and continue reading;
If your input was being provided by the console, it works with a pipe. The console is notified, will close its end of the pipe and stop sending you data.
So there's no way to reopen standard input.
BUT... there is also no reason to close standard input, so just don't do that!
A good pattern to follow is:
The code or class that opens a file is responsible for closing it.
If you pass an InputStream to another method that reads from it, that method should not close it. Leave that to the code that opened it. It's like the streams owner.
Similarly, if you pass an OutputStream to another method that writes to it, that method should not close it. Leave that to the code that owns it. BUT if you wrap the stream in other classes that may buffer some data do call .flush() on them to make sure everything comes out!
If you're writing your own wrapper classes around InputStream and OutputStream, don't close the delegate stream in your finalizer. If a stream needs to be cleaned up during GC, it should handle that itself.
In your example code, just don't close that Scanner. You didn't open standard input, so you shouldn't need to close it.
Because Streams are unbounded. You peek values from streams as you need. Then when done simply close it. Streams does not hold it's all data in memory. Streams are designed to process relatively big amount of data which can't be held in memory. So you can't reopen an stream simply because you already have made a loop over it and exhausted all the data. As stream does not hold those data in memory. They are simply lost and that's why you can't reopen it. The better is you create a new stream than reopen an existing one.
Java standard library has chosen a "standardized" approach to InputStream. Even if you may legitimately perceive some streams, such as data incoming from the input console, as logically re-openable, the InputStream represents a generic approach, as it is intended to cover all the possible InputStreams, which many of them are by their nature not re-openable. As described perfectly in #JohnBollinger's answer.
Closing and flushing IO resources is very important and seldom done correctly (at least by me). The reason for this is that most of the time, it still works without doing it correctly. Files are closed by the garbage collector, which happens from time to time in most applications. Flushing is done automatically when a stream is closed (possibly also by the garbage collector) or when a lot of data is written.
Java 1.7's try-with-resource makes it much easier to close IO resources if their lifetime coincides with the lifetime of a local variable. Not so much if they should e.g. live as long as some other object, but that is another story.
Since I started writing programs that are complex enough that I needed to use resources that wrap other resource, I instead find that it's much harder to decide what to close and/or flush than when to do it. Examples of wrapping a resource in another resource are:
Creating an InputStreamReader from an InputStream.
Creating an InputStream from a ReadableByteChannel.
Creating a DataOutputStream from an OutputStream.
Creating a PrintStream or OutputStreamWriter from an OutputStream.
This may also happen multiple layers deep, like wrapping a ReadableByteChannel in an InputStream in a GZIPInputStream in an InputStreamReader in a BufferedReader (never had to do that but seems plausible). Almost always the wrapping and the wrapped resources should have the same lifetime and it is most convenient if flushing can be done on the outermost resource, where writing is also done, so that only one object needs to be passed around.
In all this time I've never seen a satisfactory explanation of how closing and flushing interacts with resources wrapped in other resources. My assumptions are the following:
Flushing a resource (i.e. calling flush() on it) also flushes wrapped resources recursively until data is pushed onto e.g. the disk or the network.
Closing a resource (i.e. calling close() on it) also closes wrapped resources recursively until some operating system resource is freed.
Now to my question; are these assumptions correct when using JDK implementations of IO resources, specifically of the interfaces InputStream, OutputStream, ReadableByteChannel, WritableByteChannel, Reader and Writer?
If one or both assumptions are not correct at all, what assumptions would be better?
If those assumptions are not always correct, where does the behavior of an implementation differ and what are the reasons?
The question says it all.
What are the consequences of not closing the various byte streams?
It is very much emphasized to always do so, but there is no mention of how it causes problems.
Can someone please explain what actually happens?
This is not only byte streams. This concerns anything implementing Closeable.
As the documentation states:
The close method is invoked to release resources that the object is holding (such as open files).
Whether a Closeable holds system resources or not, the rule of thumb is: do not take the chance. .close() it correctly, and you'll be ensured that such system resources (if any) are freed.
Typical idiom (note that InputStream implements Closeable):
final InputStream in = whateverIsNeeded;
try {
workWith(in);
} finally {
in.close();
}
With Java 7 you also have AutoCloseable (which Closeable implements) and the try-with-resources statement, so do:
try (
final InputStream in = whateverIsNeeded;
) {
workWith(in);
}
This will handle closing in for you.
Again: don't take the chance. And if you don't use JDK 7 but can afford Guava, use Closer.
Not closing limited resources such as database connections will dramatically slow down execution, and likely result in errors as those connections run out, with old ones sitting there unused.
Not closing file-streams could result in multiple threads writing to the same file, or files not being terminated properly, or files being locked when another thread attempts to write or read it.
This is a major topic relating to all Closeables, as stated by #fge. There are numerous libraries supplying things such as connection pools and caches for handling problems such as this.
More information:
https://www.google.com/search?q=consequentes+of+not+closing+resources+java
It will hang around util collected by the GC. (thus holding to unmanaged resources (files, sockets etc)
There are several streams including:
ByteArray
File
Filter
Object
Piped
Corba version of the outputStream
Depending on the kind of resource is behind the stream the result could be different. InByteArrayInputStream and ByteArrayOutputStream where the documentation says:
Closing a ByteArrayInputStream has no effect. The methods in this
class can be called after the stream has been closed without
generating an IOException.
But in FileInputStream there is an open file. If you keept it open there is memory reserved and anybody who tries to edit the file will find it locked. In case of doubt always call the close() method.
Is there any reason for calling close methods on the StreamWriter class? Why do I have to do it? If I don't close the StreamWriter will I get some kind of undefined behavior?
Assuming you're talking about java.io.OutputStreamWriter, yes, you should close it, in a finally block, when you don't want to write anything more. This allows the underlying OutputStream to be closed. If the underlying OutputStream is a FileOutputStream, it will release the file descriptor (which is a limited OS resource), and allow other aps to read the file. If it's a SocketOutputSTream, it will signal to the other side that it shouldn't expect anything more from the socket input stream.
In general, streams and readers/writers must always be closed properly. If using Java 7, use the new try-with-resources construct to make sure it's done automatically for you.
The operating system manages files, and if in java the file is not closed, system wide resources are lost.
In java 7 you can however use
try (OutputStreamWriter outWriter = new OuputStreamWriter(outStream, "UTF-8")) {
...
}
without close. (Output streams and writers implement Closeable).
BTW #PriestVallon was just trying to make you formulate your question a bit better/attractive for answering. A "light" response to that can be misunderstood as you've seen.
Writing and reading streams involves quite often the use of os resources,as sockets,file handles and so on.if you're writing on a stream you should also close it,im order to release resources you may have obtained(it depends on the actualresources you are using beneath the stream). Sometimes closing a stream writer involves the release of an exclusive allocation of a resource, or the flushing of temporary data to the stream.
Sometimes the close is uneffective, it depends on the kind of stream you have, but the interface must take care of all the cases where a stream have to be closed.