How should I read from a buffered reader? - java

I have the following example of reading from a buffered reader:
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
The code in the loop println will be executed whenever something appears in the buffered reader (input in this case). In my case, if a client-application writes something to the socket, the code in the loop (in the server-application) will be executed.
But I do not understand how it works. inputLine = input.readLine() waits until something appears in the buffered reader and when something appears there it returns true and the code in the loop is executed. But when null can be returned.
There is another question. The above code was taken from a method which throws Exception and I use this code in the run method of the Thread. And when I try to put throws Exception before the run the compiler complains: overridden method does not throw exception. Without the throws exception I have another complain from the compiler: unreported exception. So, what can I do?

When the socket on the other end is closed, the reader should return a null string. This is the condition that you are looking for. To handle the exception, wrap the reading loop in a try/catch block.
try {
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
}
catch (IOException e) {
System.err.println("Error: " + e);
}
You might find this tutorial on reading/writing from/to a socket in Java, helpful.

For your first question:
But I do not understand how it works. inputLine = input.readLine() waits until something appears in the buffered reader and when something appears there it returns true and the code in the loop is executed. But when null can be returned.
BufferedReader.readLine() does not return true upon success. It returns a String containing the line that was read. If the end of the stream is reached, it returns null.
Your second question:
The above code was taken from a method which throws Exception and I use this code in the run method of the Thread. And when I try to put throws Exception before the run the compiler complains: overridden method does not throw exception. Without the throws exception I have another complain from the compiler: unreported exception. So, what can I do?
You should wrap your code in a try/catch block. If you don't want to handle the caught exception, simply leave that part blank (not recommended)
try {
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
} catch (Exception e) {
//handle exception
}

The reader's readLine() will return a string value when it has something read, an empty string when there isn't anything yet, and null when the connection is closed.
I would recommend wrapping a try/catch around your block of code with the IO function and handle errors appropriately.

input reader is connected to the socket, which is a listener, i.e. keeps listening to incoming messages.
About your second question, you should put a try/catch block inside the method, catch the Exception and handle it. Do not re-throw it.

But I do not understand how it works. .... waits until something appears in the
buffered reader and when something
appears there it returns true
No, it returns the value of the expression (inputLine = input.readLine()), the inputLine itself. The inputLine is compared to null.

null is returned when the "EOF (End Of File)" is reached. Since this is reading from a network socket, the end of file is created when the socket is disconnected (either by the server or the client), but you will likely get an Exception before you actually see the EOF.

If this isn't for homework, you might want to look at Apache Commons IOUtils.
Assuming you don't create the BufferedReader, and just stop at the InputStream:
String results = IOUtils.toString(inputStream);
System.out.println(results);

while ((inputLine = input.readLine()) != null) {
Look at each part of the expression:
input.readLine()
Returns a String which will be null if the end of the stream has been reached (or throws an Exception on error).
inputLine = input.readLine()
Assigns this String to inputLine
((inputLine = input.readLine()) != null)
Checks that the String that was assigned is not null (end of stream).

You have received some good answers. Just catch the exception and deal with it locally. If you need to pass this on to other code but cannot since the run() method does not allow for any check exception, you can wrap the exception in a RuntimeException of some kind. If the run method is executing directly on a Thread (since it is a Runnable probably) then you should take care with re-throwing a wrapped exception.
As for the result from readLine(), it will return null when there is nothing more to read. In the case of a socket this is when the other side cleanly closes the socket (any sudden termination or unclean close would typically result in an exception in your code as the OS will send a different kind of socket close notification).
I do have one word of caution since you are wrapping a socket in a java.io.BufferedReader. You should be very careful about using this in any kind of production code.
The danger is that BufferedReader does not deal well with exceptions in the midst of reading. This is especially an issue if you have enabled a timeout on the socket so the code will receive periodic exceptions automatically from the operating system. The timeout (or other exception) could come while the buffer inside the reader is filling. If you attempt to reuse the object after the exception, it will ignore any previous contents in the buffer. The packet(s) that were previously received are silently lost and there is no way to retrieve those bytes.
Note that there are other kinds of socket exceptions that do not mean that the socket has been lost. For instance, look at the definition of java.io.InterruptedIOException. This has a public variable that reports the number of bytes successfully transferred in the most recent I/O (read or write) request. This means that the IO operation can be executed again to retrieve or send the remaining bytes for the packet.
If upon any exception your design is to immediately close the reader and socket the method will work correctly.
The proper way to read from a socket is to use the socket stream directly, use NIO (ByteBuffers and such), or use a well written network library with good abstractions over these lower level classes (several open source ones are available).

Related

reading inputstream of a socket

I have snippet
try {
is = new BufferedReader(new inputStreamReader(getSocket().getInputStream()));
}
catch(IOException e) {}
while(true) {println(is.readLine());}
Basically, I'm tring to println every single message that is sent to the input stream of the socket returned from getSocket().
My question is:
If there is no message sent to the socket, what value is returned
from calling the readLine() method? Is it the null value or a null
string (i.e. "") or is it something else?
When a message has been
sent and has been printed out, what happened to the input stream of
the socket then? Is it emptied out?
Do we need a way to check to
only call the println() method only when the input stream HAS
something to print out?
If nothing is sent through the stream - there is nothing to read yet. Your reader is just waiting.
It is emptied out only from the data you have received.
You should have the while(true) loop which is trying to read the line from the stream. You do not have to check anything.
If the socket is closed at the second side, reader is reading null. If the second side has exited without closing the socket, you get IOException.
If there is no message sent to the socket, what value is returned from calling the readLine() method? Is it the null value or a null string (i.e. "") or is it something else?
Neither. It blocks.
When a message has been sent and has been printed out, what happened to the input stream of the socket then? Is it emptied out?
No. The data received has been removed from it. There may be further pending data waiting be read.
Do we need a way to check to only call the println() method only when the input stream HAS something to print out?
No. It blocks until a line has been received, end of stream occurs, or an IOException is thrown.
Your read loop isn't correct. It doesn't detect end of stream. The usual way to write it is:
while ((line = in.readLine()) != null)
// ...

Regarding data read from TCP connection

I am making a client socket connection with a hardware device. I am sending a command to this connection to be process by hardware. Now as a acknowledgment or as a reply, the hardware sends a response.
The application sends a command to the connection periodically say in 10 seconds.
Now there exists a problem randomly that the response won't gets synchronized with the sent command from the application. I was thinking of this as hardware specific but to my surprise, when I see the response by connecting putty to the same hardware at same port, I can see that response always gets synchronized. This looks like putty under the hood using some criteria to map the request to response.
Below is the programming steps that I am using to send a command to hardware device:-
Socket clientSocket = new Socket(<IPADDRESS>, 4001);
DataOutputStream outToServer = new DataOutputStream(
clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
while (true) {
try {
//Get command randomly from array enums for test
Random r = new Random();
Commands[] array = Commands.values();
String command = (String) array[r
.nextInt(Commands.values().length)].getCommand();
outToServer.writeBytes(command);
Thread.sleep(500);
while (!inFromServer.ready()) {
}
System.out.println("COMMAND "+command+", SERVER RESPONSE: "
+ inFromServer.readLine());
Thread.sleep(1500);
} catch (SocketTimeoutException se) {
//Handle Exception
} catch (SocketException se) {
//Handle Exception
}
Can anybody gives a advice how the synchronization of response with request can be achieved as mechanism like putty?
Putty doesn't know any more about your device than you do. The problem is in your code. Get rid of the ready() test and the sleep(). Just call readLine(), if you can be sure that the device sends lines, otherwise just call InputStream.read().
Remove the thread sleep, and rewrite read like this:
String line;
while ((line = inFromServer.readLine()) != null) {
System.out.println("COMMAND "+command+", SERVER RESPONSE: "
+ line);
}
This code can still hang, if the device sends the last message without the newline character \n. Your original code skipped the input.
The main problem is with this line:
while (!inFromServer.ready()) {
InputStreamReader#ready is OK to use only when you have other means to know that all the data has been sent:
Tells whether this stream is ready to be read. An InputStreamReader is ready if its input buffer is not empty, or if bytes are available to be read from the underlying byte stream.
The first message will get read, but that empties the buffer, and when the second message arrives your code isn't reading anymore. You would have to have as many loops as there are messages from device, and that's not practical, at least. And in that case also, it would probably not work all the time.
On the other hand the BufferedReader#readLine:
Returns:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
will read until all the data that was sent has been read. But if your device send no new line character, then this method will never read the line - the code will hang with all the data in the buffer. In that case you should use InputStreamReader#read as EJP suggested:
Returns:
The character read, or -1 if the end of the stream has been reached
I strongly suggest that you read the IO Streams official tutorial.
Generally speaking, waiting is not done by Thread.sleep and busy waiting (executing empty statements), e.g.:
while (true) {} /*or*/ while(true);
The CPU is executing the empty statement, and it could be doing some other work while waiting on this one to complete. It is a bad practice.
If you want to know more on how to implement waiting I recommend reading the official concurrency tutorial or this one for a broader approach on the matter.

android socket write interrupting read

Using android 2.3.3, I have a background Service which has a socket connection. There's a Thread that's reading from the socket continuously:
BufferedReader in = new BufferedReader(new InputStreamReader(mSock.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
... do stuff
}
// Socket has been closed (?)
in.close();
And then in my main thread I call:
private void writeSocket(String line) {
mSock.getOutputStream().write(line.getData("US-ASCII"));
}
When I call writeSocket, the write() does not throw an exception but I don't see the data at the other end, and the in.readLine() in the reading thread immediately returns null when the write() occurs. From what I read, it should be safe to read and write simultaneously with the same socket from different threads? It seems like the write is causing the socket to close, but I don't get an exception..
Most likely, the other end of the connection was closed normally. This causes both the read and write to terminate. (Normally, so no exception. It's just like trying to read past the end of a file.) You can read and write simultaneously from different threads and if the socket closes, whether normally or exceptionally, both operations will fail.

Server Socket Input Stream returning null before disconnect

I am trying to deal with client disconnects in a simple java application that sends chat messages using a client and a server.
Here's the problem
public void run() {
try {
System.out.println("Client Connected");
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
theServer.handle(inputLine, this);
}
out.close();
in.close();
socket.close();
System.out.println("Client Disconnected");
} catch (Exception e) {
e.printStackTrace();
}
}
With this code here, it runs the while loop while the input line is not null. If it is null then it will stop looping and close the in and out streams as well as the socket. Now, this is all working fine apart from the output in the console is this:
Client Connected
null
Client(/127.0.0.1): null
null
Client(/127.0.0.1): null
null
Client(/127.0.0.1): null
null
Client(/127.0.0.1): null
Client Disconnected
I can't figure out why the loop would keep looping even when the input is null!! It seems to take a while to realise that it's null before exiting the loop. I need it to exit straight away without a delay.
Any help would be appreciated,
shadrxninga
The only explanations that I can think of are:
in.readLine() is returning the string "null" (possibly with trailing whitespace),
in refers to some custom stream or reader wrapper whose readLine() method is doing something weird, or
this is not the code that you are actually executing.
You say:
"It seems to take a while to realise that it's null before exiting the loop."
This is a "voodoo programming" explanation. It cannot possibly be correct unless there's a bug in your Java implementation. And that is extremely unlikely.
Well it looks like that the null being returned is in the form string so that's why it's behaving this way.

How to timeout a read on Java Socket?

I'm trying to read items from a socket and I notice that if there is nothing on the stream of the socket it will stay at the read and back up my application. I wanted to know if there was a way to set a read timeout or terminate the connection after a certain amount of time of nothing in the socket.
If you write Java, learning to navigate the API documentation is helpful. In the case of a socket read, you can set the timeout option, e.g.:
socket.setSoTimeout(500);
This will cause the InputStream associated with the socket to throw a SocketTimeoutException after a read() call blocks for one-half second. It's important to note that SocketTimeoutException is unique among exceptions thrown by such read() calls, because the socket is still valid; you can continue to use it. The exception is only a mechanism to escape from the read and decide if it's time to do something different.
while (true) {
int n;
try {
n = input.read(buffer);
catch (SocketTimeoutException ex) {
/* Test if this action has been cancelled */
if (Thread.interrupted()) throw new InterruptedIOException();
}
/* Handle input... */
}
If this socket was created through a URLConnection to perform a web request, you can set the read and connect timeouts directly on the URLConnection before reading the stream:
InputStream createInputStreamForUriString(String uriString) throws IOException, URISyntaxException {
URLConnection in = new URL(uriString).openConnection();
in.setConnectTimeout(5000);
in.setReadTimeout(5000);
in.setAllowUserInteraction(false);
in.setDoInput(true);
in.setDoOutput(false);
return in.getInputStream();
}
Yes, there should be an override of Read() that accepts a timeout value. By 'override' I am not suggesting anyone write one, I am pointing out that one of the overrides of the socket methods he is using takes a timeout value.

Categories

Resources