Closing Reader/Stream in Java [duplicate] - java

This question already has an answer here:
How can I fix an "IOException: Stream closed" exception using System.in?
(1 answer)
Closed 7 years ago.
In my code I have to read user input from console:
class Demo {
//...some code
public String readUserInput() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String userInput = reader.readLine();
reader.close();
return userInput;
}
}
On first time when I use method readUserInput() on Demo object everything is OK. But when I create another Demo object and call method - it throws Exception with the message
"Stream closed"
Can anybody tell me, why I have Exception on different not equal objects? Thank you for your attention.

The problem is here:
new InputStreamReader(System.in)
When you close your BufferedReader, it closes the InputStreamReader, which in turn closes System.in.
This is all (kind of) explained in the contract of Closeable's .close(), which says:
Closes this stream and releases any system resources associated with it.
As a result, the second time you try and read from your BufferedReader, this ultimately results in data being read from System.in, but it is unavailable. Hence your error.
More generally, you handle your resources poorly. Please read about, and learn to use, the try-with-resources statement.

You are closing the reader, which close... System.in
In this case, you don't have to close the Stream.

Related

The Properties.load would close the InputStream?

I saw this example, and I didn't see the close() method invoked on the InputStream, so would prop.load() close the stream automatically? Or is there a bug in the example?
The Stream is not closed after Properties.load ()
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(new File("abc.properties"));
new Properties().load(in);
System.out.println(in.read());
}
The above code returns "-1" so the stream is not closed. Otherwise it should have thrown java.io.IOException: Stream Closed
Why do you ask when the javadoc of Properties.load(InputStream inStream) says this?
The specified stream remains open after this method returns.
It has been saying that since Java 6.
As EJP said in a comment: Don't rely on arbitrary Internet junk. Use the official Oracle Java documentation as your primary source of information.
The following try-with-resources will close the InputStream automatically (you can add catch and finally if needed):
try (InputStream is = new FileInputStream("properties.txt")) {
// is will be closed automatically
}
Any resource declared within a try block opening will be closed. Hence, the new construct shields you from having to pair try blocks with corresponding finally blocks that are dedicated to proper resource management.
Article by Oracle here: http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html.

Java Try-with-resource storing input stream in Map

In my API (Spring boot) I have an endpoint where users can upload multiple file at once. The endpoint takes as input a list of MultipartFile.
I wish not to directly pass this MultipartFile object to the service directly so I loop through each MultipartFile and create a simple map that stored the filename and its InputStream.
Like this:
for (MultipartFile file : files) {
try (InputStream is = multipartFile.getInputStream()) {
filesMap.put(file.getOriginalFilename(), is);
}
}
service.uploadFiles(filesMap)
My understanding for Java streams and streams closing is quite limited.
I thought that try-with-resources automatically closes the InputStream once the code reached the end of the try block.
In the above code when does exactly the the multipartFile.getInputStream() gets closed?
The fact that I'm storing the stream in a map will that cause a memory leak?
Stream closes right after execution reaches closing bracket of try block.
It is okay to store InputStream anywhere after you closed it.
But be aware of that you can't read anything from this stream after you closes it.
Thanks to comments
Also, be aware of that some streams have special behavior on close() and it always depends on Stream realization.
For example:
If you try to read from closed FileInputStream you will get
java.io.IOException: Stream Closed
If you try to read from closed ByteArrayInputStream it will be okay, because of it's special close() realization: public void close() throws IOException {}
When does exactly the multipartFile.getInputStream() gets closed?
try (InputStream is = multipartFile.getInputStream()) {
filesMap.put(file.getOriginalFilename(), is);
} // <-- here
The try-with-resources statement ensures that each resource is closed at the end of the statement.
The fact that I'm storing the stream in a map will that cause a memory leak?
No, your collection just keeps closed InputStreams and you won't be able to read from them (in addition, you will get IOException).

Java Deserialization -- file is correctly written to but calling .available() on the ObjectInputStream with the same file path always returns 0 [duplicate]

This question already has answers here:
ObjectInputStream available() method doesn't work as expected (Java)
(5 answers)
Closed 6 years ago.
First of all, I'm new to the site, and found it very helpful for having previous questions of mine that had already been answered, but I couldn't find anything about this specifically, so I hope this hasn't already been answered. This is for a game I'm making where RoadPanel.shopList is a static arraylist that holds all the shops in the map (and they are drawn and updated, etc. from here). shopIn has the same filepath as the file that is (correctly) written to while the game is running (I opened the file to make sure it was being written to properly). I don't know why it says that there are no available files to read from the InputStream, so I'm really stuck...
public static void loadGame() throws ClassNotFoundException, IOException
{
ObjectInputStream shopIn = new ObjectInputStream(new FileInputStream("src/save/shops.ser"));
System.out.println("Available: " + shopIn.available());
while(shopIn.available() > 0)
{
System.out.println("hit");
Shop s = (Shop)shopIn.readObject();
RoadPanel.shopList.add(s);
}
}
Thanks for your help,
pete.
Your code is invalid. available() isn't a test for end of stream. See the Javadoc. And it isn't implemented for some streams, including ObjectInputStream.
You should read until EOFException is thrown.

Is a file opened with newBufferedReader closed if an Exception occurs?

I usually open files by fetching a BufferedReader:
Files.newBufferedReader(myPath).lines()
.doStuff()
.doMoreStuff();
What happens when the method throws an Exception, will the Reader be closed automatically like with a try-with-resource? I found no reference in the docs.
The Files.newBufferedReader is just a utility/factory method to create a BufferedReader for the File. Internally it eventually does a new BufferedReader() to create the BufferedReader.
So, you would have to treat it the same way as you would create the BufferedReader using the new operator. If you want it to be auto-closed at the end of the try block, you would have to use the try-with-resource as you would, if you had to create it using the new operator.

Why DataoutputStream and BufferedWriter creation order is important? [duplicate]

This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 8 years ago.
I'm trying to create a simple client where at first I comunicate to a server:
A filename
The sequence of chunks which compose the file
So for the first one I thought to use to a BufferedWriter: this choice was made since I can't use on the server a InputStreamReader from the moment that the readLine() method is deprecated. However, for the second one I used a OutputStreamWriter since it is the better (only?) one choice to write a byte array on a socket.
So, this is the first version of my client code:
public class Client
{
private static final int PART_SIZE = 1000000; // 1MB
public static void main(String[] args) throws IOException
{
final Path file = Paths.get(args[0]);
final String filenameBase = file.getFileName().toString();
final byte[] buf = new byte[PART_SIZE];
Socket socket = new Socket(InetAddress.getLocalHost(),8080);
System.out.println("Socket created");
int partNumber = 0;
Path part;
int bytesRead;
byte[] toWrite;
try (
final InputStream in = Files.newInputStream(file);
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
final DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
) {
System.out.println("closed="+socket.isClosed());
bw.write(filenameBase,0,filenameBase.length());
//other stuff for the chunk creation and spedition
}
}
}
However, if I run this code, this exception occours:
Exception in thread "main" java.net.SocketException: Socket closed
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:121)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implClose(StreamEncoder.java:316)
at sun.nio.cs.StreamEncoder.close(StreamEncoder.java:149)
at java.io.OutputStreamWriter.close(OutputStreamWriter.java:233)
at java.io.BufferedWriter.close(BufferedWriter.java:266)
at PAD.Charlie.Client.App.main(App.java:50)
The strange thing is that if I change the order between the BufferedWriter and the DataOutputStream inside the try everthing works fine!
Actually the idea has come because I remembered something about it from the java course, but I can't really remember the details! Can you help me about this doubt that I have? Thanks a lot! :)
First of all, what you are doing is borderline crazy. You appear to be intending to write both text and binary data the same stream:
It is going to be difficult to control the interleaving of the two kinds of data since you are using a buffered writer at that point in the stack.
Even if you get the interleaving right, the "other end" has the problem of unpicking it to separate the text and binary.
You attempt to justify your decision use two stream stacks on the output stream as follows:
So for the first one I thought to use to a BufferedWriter: this choice was made since I can't use on the server a InputStreamReader from the moment that the readLine() method is deprecated. However, for the second one I used a OutputStreamWriter since it is the better (only?) one choice to write a byte array on a socket.
I don't follow your logic. But the fact that one approach doesn't work does not necessarily mean that (any) other one will.
If you want a solution that will work, then I can think of a few. The simplest is to use DataOutputStream only on the client side, and use writeUTF to write the file name and writeInt + write to write the chunks. Indicate the end of file by sending a chunk size of zero.
(You could also send the file as one big chunk if you know beforehand how many bytes you will be sending.)
The server-side code should mirror the client-side in its calls on a DataInputStream.
But the reason for difference in behaviour that you are seeing is that the order of the declarations in the try initializations determines the order in which the streams are closed at the end of the try block.
If the writer is closed first then:
BufferedWriter.close()
-> BufferedWriter.flush() -> OutputStreamWriter.write()
-> OutputStreamWriter.close() -> SocketOutputStream.close()
DataOutputStream.close() -> SocketOutputStream.close()
This is OK because the second set of closes does not need to write any data.
If the writer is closed second then:
DataOutputStream.close() -> SocketOutputStream.close()
BufferedWriter.close()
-> BufferedWriter.flush() -> OutputStreamWriter.write() // FAIL
The failure happens because the flush cannot write data to the socket because you have already (implicitly) closed it.
Because closing the BufferedWriter flushes it, and if you create the writer first it will be closed last, after the stream, and closing either of them closes the socket. See the stack trace. DataOutputStream isn't buffered, so flushing it does nothing.
NB:
... since I can't use on the server a InputStreamReader from the moment that the readLine() method is deprecated. However, for the second one I used a OutputStreamWriter since it is the better (only?) one choice to write a byte array on a socket.
None of this makes sense. InputStreamReader doesn't have a readLine() method, let alone one that is deprecated; and OutputStreamWriter writes chars, not bytes.

Categories