3

Here is my question: normal while loop looks like this -

while(condition){statements} 

and statements execute until condition becomes false and the loop is over. I'm interested in logic of this kind of statement:

while((a=b.readLine) != null) { ... } 

It's used in client - server communication in my case. The condition is sometimes true, sometimes isn't, but loop looks like it's testing the condition forever and when true, statements in {} execute. It looks to me that loop waits for the condition to be true and then runs statements. Is it somehow linked to the way BufferedReader and InputStreamReader work or what? Also, it seems this loop is never over, it just waits for a condition to be true and then runs statements, and then again waits for a condition to be true, etc. I would be thankful for any clarification.

user207421
  • 305,947
  • 44
  • 307
  • 483
Seba
  • 33
  • 1
  • 1
  • 5
  • If you send a `null` object to the server you are referring to it would kick out. – 3kings Mar 24 '16 at 21:03
  • 1
    `BufferedReader`, when calling `readLine()`, will return `null` when it exhausts all the lines of a file – Maljam Mar 24 '16 at 21:04
  • @3kings Nonsense. You can't 'send a null object'. The loop terminates when `readLine()` returns null, which it does at end of stream. See the Javadoc. – user207421 Mar 24 '16 at 21:10
  • Understood, but, when readLine() exhausted all lines, loop still isn't over(though condition becomes false), it waits for another line to appear (from server) to be read, and again runs its code and it looks that this loop is forever alive waiting for condition to be true. If condition is false(when there's nothing to read) it still isn't dead, it waits for situation when condition will become true again – Seba Mar 24 '16 at 21:10
  • The only tricky thing about that line is that has a comparison on an expression with an assignment. It assigned the `a` for later use, before checking the value. This is part of the language and nothing to do with the class. – Peter Lawrey Mar 24 '16 at 21:12
  • @Seba No, when `readLine()` returns null the loop terminates. – user207421 Mar 24 '16 at 21:13
  • The `readLine()` only returns when either it reaches a newline of the stream is close(). If you are reading a socket and nether of these things happen it will block. – Peter Lawrey Mar 24 '16 at 21:13
  • And normal while loop is over when its condition becomes false. This one is different, when there's nothing to read, loop isn't terminated, it waits for something to be read, i.e. condition to be true... How to explain that difference? – Seba Mar 24 '16 at 21:13
  • The `readLine()` is blocking waiting for data or the stream to be closed. – Peter Lawrey Mar 24 '16 at 21:14
  • That's the behaviour of `readLine()`. It blocks until a line is transferred or end of stream or an exception occurs. This is called blocking I/O. – user207421 Mar 24 '16 at 21:15
  • These answers have been very helping to me. Now I understand. – Seba Mar 24 '16 at 22:17

4 Answers4

6
while((a = b.readLine()) != null){ ... }

At each iteration, the condition inside the parentheses is evaluated.

Evaluating this expression consists in calling b.readLine(), affecting the returned value to a, and comparing a with null.

Calling readLine(), as documented, consists in blocking until the next line is read. If there is no next line, readLine() returns null.

So, in short, this while loop reads every line from the reader, does something with the line (inside the while block) and stops when the end of the stream is reached.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
5

The following code snippet

String a;
while((a = b.readLine()) != null) { // a = b.readLine() -> a -> a != null
    ... 
}

is equivalent to

String a = b.readLine();
while(a != null) {
    ...
    a = b.readLine();
}

but the first way is more simple, readable, and Java allows using assignment operators here because they return the value of a renewed variable.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • Dear Andrew, I'm afraid you are very wrong, both codes are not the same. The first one like you have rightly said is the correct one but the second code will loop forever when something is read by b.readLine(). – Christian Oliver Dec 09 '19 at 11:23
4

This idiom

while ( (a = b.readLine()) != null) {  /* body */ }

is a normal while loop, but the condition happens to contain an embedded assignment operator, which yields the result of the assignment, which is compared to null.

Whether b is reading from a socket, a file, or any other input stream, presumably b is something like a BufferedReader with its readLine() method. This method will only return null when the end of the stream is reached. It will block if the end of the stream hasn't been reached yet, but not further input consisting of a newline character has been read off the stream yet.

When such a line is available, a is not null and the body of the loop executes. The result of readLine is assigned to a for convenient processing withing the body of the loop.

When the end of the stream is reached, a is null and the while loop ends.

This idiom allows for easy processing of an entire stream of data, whether it is from an entire file, from an entire socket connection, or otherwise generally reading from an entire input stream of data. It looks more complicated than a simpler while loop, but it's just a standard while loop with a more complicated condition.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • I was doing some client - server chatting applications via socket connection. It means that nucleus of my question is actually readLine() method's nature. So this loop will be terminated when end of stream is reached... But when is that? When stream is closed? – Seba Mar 24 '16 at 21:25
  • Closing the stream from the other end of the socket will do this; closing the socket itself will close its streams too. – rgettman Mar 24 '16 at 21:27
  • So basically, this loop runs until stream or socket is closed. It is not terminated, no matter nothing comes to be read. Its's not terminated until stream is dead? – Seba Mar 24 '16 at 21:33
  • 1
    It won't be terminated until the stream is closed (or until an `IOException` occurs). – rgettman Mar 24 '16 at 21:36
  • I'm very thankful and in the same time apologize. I'm learning java for couple of months and I've done some research on this question, but here I've found most satisfying answer. – Seba Mar 24 '16 at 21:42
0

Because most IO streams don't read all data at once but bits-by-bits, putting the read() or readLine() assignment as part of the WHILE condition ensures that the WHILE block continues to loop as the input stream is read bits-by-bits until there's nothing to left to read (that is, all data have been read).