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.
Related
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.
In the following scenario
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.flush();
// Do stuff with it
Why is it always necessary to flush the buffer after initial creation?
I see this all the time and I don't really understand what has to be flushed. I kind of expect newly created variables to be empty unless otherwise is specified.
Kind of like buying a trash-can and finding a tiny pile of trash inside that came with it.
In over 15 years of writing Java on a professional level I've never once encountered a need to flush a stream before writing to it.
The flush operation would do nothing at all, as there's nothing to flush.
You want to flush the stream before closing it, though the close operation should do that for you it is often considered best practice to do it explicitly (and I have encountered situations where that did make a difference, where apparently the close operation did not actually do a flush first.
Maybe you are confused with that?
When you write data out to a stream, some amount of buffering will occur, and you never know for sure exactly when the last of the data will actually be sent. You might perform many rite operations on a stream before closing it, and invoking the flush()method guarantees that the last of the data you thought you had already written actually gets out to the file. Whenever you're done using a file, either reading it or writing to it, you should invoke the close()method. When you are doing file I/O you're using expensive and limited operating system resources, and so when you're done, invoking close()will free up those resources.
This is needed when using either ObjectInputStream and ObjectOutputStream, because they send a header over the stream before the first write is called. The call to flush() will send that header to the remote side.
According to the spec, the header exists of the following contents:
magic version
If the header doesn't arrive at the moment a ObjectInputStream is build, this call will hang until it received the header bytes.
This means that if the protocol in question is written with ObjectStreams, it should flush after creating a ObjectOutputStream.
I am trying to understand piped streams.
Instead of piped stream why can't we use other streams to pipe each other? like below:
final ByteArrayOutputStream pos = new ByteArrayOutputStream();
final ByteArrayInputStream pis = new ByteArrayInputStream(pos.toByteArray());
and when will we have a deadlock in a piped stream? I tried to read and write using single main thread, but it executes smoothly.
The difficulty here is that the process must be implemented in several threads because writing to one end of the pipe must be matched with a read at the other end.
It is certainly not difficult to create a thread to monitor arrivals at the end of one pipe and push them back through another pipe but it cannot be done with a single thread.
Have you looked at this question?
Piped streams allow for efficient byte-by-byte processing with minimal effort.
I could very well be wrong, but I believe toByteArray() might not do what you think it does. It just copies the current contents, not any contents in future.
So the only real issue here is management of this, which would be a bit more difficult. You'd have to constantly poll the output stream. Not to mention the memory allocation of an array for each call to toByteArray (which "Creates a newly allocated byte array" for each call).
How I suspect deadlocks may happen in a single thread:
If you try to (blocking) read from an input stream that doesn't have data yet. It will never be able to get data because data can only be obtained from the output stream to which must be written in the same thread, which can't happen while you're sitting waiting for data.
So, in a single thread, it will happen if you're not very careful, but it should be possible to successfully use them in the same thread without deadlocks, but why would you want to? I think another data structure may be better suited, like a linked-list or simple circular array.
I want to invoke an external program in java code, then the Google tell me that the Runtime or ProcessBuilder can help me to do this work. I have tried it, and there come out a problem the java program can't exit, that means both the sub process and the father process wait for forever. they are hanging or deadlock.
Someone tell me the reason is that the sub process's cache is too small. when it try to give back data to the father process, but the father process don't read it in time, then both of them hang. So they advice me fork an thread to be in charge of read sub process's cache data. I do it as what they tell me, but there still some problem.
Then I close the output stream which get by the method getOutputStream(). Finally, the program success. But I don't know why it happen? Is there some relationship between the output steam and input stream?
You have provided very few details in your question, so I can only provide a general answer.
All processes have three standard streams: standard input, standard output and standard error. Standard input is used for reading in data, standard output for writing out data, and standard error for writing out error messages. When you start an external program using Runtime.getRuntime().exec() or ProcessBuilder, Java will create a Process object for the external program, and this Process object will have methods to access these streams.
These streams are accessed as follows:
process.getOutputStream(): return the standard input of the external program. This is an OutputStream as it is something your Java code will write to.
process.getInputStream(): return the standard output of the external program. This is an InputStream as it is something your Java code will read from.
process.getErrorStream(): return the standard error of the external program. This is an InputStream as, like standard output, it is something your Java code will read from.
Note that the names of getInputStream() and getOutputStream() can be confusing.
All streams between your Java code and the external program are buffered. This means each stream has a small amount of memory (a buffer) where the writer can write data that is yet to be read by the reader. The writer does not have to wait for the reader to read its data immediately; it can leave its output in the buffer and continue.
There are two ways in which writing to buffers and reading from them can hang:
attempting to write data to a buffer when there is not enough space left for the data,
attempting to read from an empty buffer.
In the first situation, the writer will wait until space is made in the buffer by reading data out of it. In the second, the reader will wait until data is written into the buffer.
You mention that closing the stream returned by getOutputStream() caused your program to complete successfully. This closes the standard input of the external program, telling it that there will be nothing more for it to read. If your program then completes successfully, this suggests that your program was waiting for more input to come when it was hanging.
It is perhaps arguable that if you do run an external program, you should close its standard input if you don't need to use it, as you have done. This tells the external program that there will be no more input, and so removes the possibility of it being stuck waiting for input. However, it doesn't answer the question of why your external program is waiting for input.
Most of the time, when you run external programs using Runtime.getRuntime().exec() or ProcessBuilder, you don't often use the standard input. Typically, you'd pass whatever inputs you'd need to the external program on the command line and then read its output (if it generates any at all).
Does your external program do what you need it to and then get stuck, apparently waiting for input? Do you ever need to send it data to its standard input? If you start a process on Windows using cmd.exe /k ..., the command interpreter will continue even after the program it started has exited. In this case, you should use /c instead of /k.
Finally, I'd like to emphasise that there are two output streams, standard output and standard error. There can be problems if you read from the wrong stream at the wrong time. If you attempt to read from the external program's standard output while its buffer is empty, your Java code will wait for the external program to generate output. However, if your external program is writing a lot of data to its standard error, it could fill the buffer and then find itself waiting for your Java code to make space in the buffer by reading from it. The end result of this is your Java code and the external program are both waiting for each other to do something, i.e. deadlock.
This problem can be eliminated simply by using a ProcessBuilder and ensuring that you call its redirectErrorStream() method with a true value. Calling this method redirects the standard error of the external program into its standard output, so you only have one stream to read from.
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.