Closing BufferedReader without closing wrapped stream - java

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.

Related

Should I always close BufferedReader?

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.

Why is it necessary to flush the output buffer when it was just created?

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.

Using StreamWriter.close() in Java

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.

What happens when an input Buffer in Java gets flushed automatically?

I just read that
Some buffered output classes support autoflush, specified by an
optional constructor argument. When autoflush is enabled, certain key
events cause the buffer to be flushed. For example, an autoflush
PrintWriter object flushes the buffer on every invocation of println
or format.
So if I am keeping the reference of any BufferReader for some time being and it gets flushed , then how all the data will be retained back? Is there some call back mechanism that will automatically flush it and again read the content or will I lose the data and again I need to call for it?
So if I am keeping the reference of any BufferReader for some time being and it gets flushed , then how all the data will be retained back?
I think you mean BufferedWriter. (Neither the Reader or InputStream APIs have a flush() method. Flushing doesn't make any sense on a "source".)
The flushed data is written to the stream's "sink"; i.e. the file or socket or whatever. So if you look in the file (or whatever), the data will be there if the stream has been flushed (successfully).
Is there some call back mechanism that will automatically flush it and again read the content
There is no callback mechanism1. (At least, not in any of the buffered stream classes that the standard class library provides: who knows what a custom class might do ...)
Data is flushed automatically when certain things happen. For example, when the application calls println ... for a PrintWriter.
... or will I lose the data and again I need to call for it?
This doesn't make sense, either grammatically or semantically. I don't know what you are trying to ask.
Perhaps you don't understand what flushing does. Flushing simply means pushing the data out of the buffers and out to wherever the stream sends its data. An explicit flush() call or an automatic flush just means "write it NOW".
1 - Incidentally, BufferedWriter doesn't have a finalize() method either. This means that if one of these objects becomes unreachable while it still has output buffered, that output will never be written.
I think you're getting confused between buffered readers and writers. Your statement is talking about buffered writers, so if you're writing out to a stream then you shouldn't really care whether it is physically written or only written to the buffer - it doesn't matter to Java.
I would hope that a buffered reader would never be flushed, but depending on the type of buffer it might be OK. For example, if reading from a file, the buffer could be flushed and the file would just need to be re-read from the file system when you try to read(). However, for other streaming content, you wouldn't want it to be automatically flushed, as you would lose whatever data was in the buffer.

How to delete buffered data in a buffered OutputStream?

It is possible to skip data from an InputStream
in.skip(in.available());
but if you want to do something similar with OutputStream I've found
socket.getOutputStream().flush();
But that's not the same, flush will transmit the buffered data instead of ignoring it.
Is there any possibility of deleting buffered data?
Thanks
EDIT
The situation is a client-server application, when a new command is send (from client)
it (try) to be sure that the answer read will correspond to the last command sent.
Some commands are sent by (human-fired) events, and others are sent by automatic threads.
If a command is on buffer and a new one is send then the answer will be for the first one, causing desynchronization.
Of course a synchronized method plus a flag called "waitingCommand" could be the safer approach but as the communication is not reliable, this approach is slow (depends on timeouts ). That's why I've asked for the skip method.
You can't remove data you could have sent. You can write the data into an in-memory OutputStream like ByteArrayOutputStream and copy only the portions you want.
I'm no sure if it makes sense, but you can try:
class MyBufferedOutputStream extends java.io.BufferedOutputStream {
public MyBufferedOutputStream(OutputStream out) {
super(out);
}
/** throw away everything in a buffer without writing it */
public synchronized void skip() {
count = 0;
}
}
What does it mean to "skip" outputting data?
Once the data is in the buffer, there's no way to get it back or remove it. I suggest checking if you want to skip the data before you write it to the OutputStream. Either that, or have your own secondary buffer that you can modify at will.
This question doesn't make any sense. Throwing away pending requests will just make your application protocol problem worse. What happens to the guy that is waiting for the response to the request that got deleted? What happened to the functionality that that request was supposed to implement? You need to rethink all this from another point of view. If you have a single connection to a server that is executing request/response transactions for this client, the protocol is already sequential. You will have to synchronize on e.g. the socket at the point of writing & flushing the request and reading the response, but you're not losing any performance by this as the processing at the other end is sequentialized anyway. You don't need a 'waitingCommand' flag as well, just synchronization.
Since you are controlling the data written to OutputStream, just don't write pieces that you don't need. OutputStream by contract, does not ensure when data is actually written, so it doesn't make much sense to have skip method.
The best you can do to "ignore" output data, is not to write it at first.

Categories