цикл while с readLine ()

Вот мой вопрос: нормальный цикл while выглядит так -

while(condition){statements} 

и операторы выполняются до тех пор, пока условие не станет false и цикл не завершится. Меня интересует логика такого утверждения:

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

В моем случае он используется в общении клиент-сервер. Условие иногда истинно, иногда нет, но цикл выглядит так, как будто он постоянно проверяет условие, и когда оно истинно, инструкции в {} выполняются. Мне кажется, что цикл ожидает выполнения условия, а затем выполняет операторы. Это как-то связано с тем, как работают BufferedReader и InputStreamReader или как? Кроме того, кажется, что этот цикл никогда не заканчивается, он просто ждет, пока условие не станет true, а затем запускает операторы, а затем снова ждет, когда условие будет true, и т. Д. Я был бы благодарен за любые разъяснения.


person Seba    schedule 24.03.2016    source источник
comment
Если вы отправите объект null на сервер, на который вы ссылаетесь, он отключится.   -  person 3kings    schedule 25.03.2016
comment
BufferedReader при вызове readLine() вернет null, когда исчерпает все строки файла   -  person Maljam    schedule 25.03.2016
comment
@ 3kings Чепуха. Вы не можете «отправить нулевой объект». Цикл завершается, когда readLine() возвращает значение null, что происходит в конце потока. См. Javadoc.   -  person user207421    schedule 25.03.2016
comment
Понятно, но, когда readLine () исчерпал все строки, цикл все еще не завершен (хотя условие становится ложным), он ждет, пока появится другая строка (с сервера) для чтения, и снова запускает свой код, и кажется, что это цикл вечно жив, ожидая выполнения условия. Если условие ложно (когда нечего читать), оно все еще не мертво, оно ждет ситуации, когда условие снова станет истинным.   -  person Seba    schedule 25.03.2016
comment
Единственная сложность в этой строке - это сравнение выражения с присваиванием. Он присвоил a для последующего использования перед проверкой значения. Это часть языка и не имеет отношения к классу.   -  person Peter Lawrey    schedule 25.03.2016
comment
@Seba Нет, когда readLine() возвращает ноль, цикл завершается.   -  person user207421    schedule 25.03.2016
comment
readLine() возвращается только тогда, когда он достигает новой строки потока close (). Если вы читаете сокет, но ничего подобного не происходит, он блокируется.   -  person Peter Lawrey    schedule 25.03.2016
comment
И нормальный цикл while завершается, когда его условие становится ложным. Этот другой, когда читать нечего, цикл не завершается, он ждет, пока что-то будет прочитано, т.е. условие будет истинным ... Как объяснить эту разницу?   -  person Seba    schedule 25.03.2016
comment
readLine() блокирует ожидание закрытия данных или потока.   -  person Peter Lawrey    schedule 25.03.2016
comment
Это поведение readLine(). Он блокируется до тех пор, пока строка не будет передана, или до конца потока, или до тех пор, пока не произойдет исключение. Это называется блокировкой ввода-вывода.   -  person user207421    schedule 25.03.2016
comment
Эти ответы мне очень помогли. Теперь я понимаю.   -  person Seba    schedule 25.03.2016


Ответы (4)


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

На каждой итерации оценивается условие, указанное в скобках.

Оценка этого выражения заключается в вызове b.readLine(), изменении возвращаемого значения на a и сравнении a с нулем.

Вызов readLine(), как описано в документации, заключается в блокировке до тех пор, пока не будет прочитана следующая строка. Если следующей строки нет, readLine() возвращает null.

Короче говоря, этот цикл while читает каждую строку из считывателя, что-то делает с этой строкой (внутри блока while) и останавливается, когда достигается конец потока.

person JB Nizet    schedule 24.03.2016

Следующий фрагмент кода

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

эквивалентно

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

но первый способ более простой, читаемый, и Java позволяет использовать здесь операторы присваивания, поскольку они возвращают значение обновленной переменной.

person Andrew Tobilko    schedule 24.03.2016
comment
Уважаемый Андрей, боюсь, вы сильно ошибаетесь, оба кода не совпадают. Первый, как вы правильно сказали, является правильным, но второй код будет зацикливаться вечно, когда что-то читается с помощью b.readLine (). - person Christian Nwafor; 09.12.2019

Эта идиома

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

- это нормальный цикл while, но условие содержит встроенный оператор присваивания, который дает результат присваивания, который сравнивается с null.

Независимо от того, читает ли b из сокета, файла или любого другого входного потока, предположительно b является чем-то вроде BufferedReader с его readLine() методом. Этот метод вернет null только тогда, когда будет достигнут конец потока. Он будет заблокирован, если конец потока еще не достигнут, но дальнейший ввод, состоящий из символа новой строки, еще не считан из потока.

Когда такая строка доступна, a не null, и выполняется тело цикла. Результат readLine присваивается a для удобной обработки в теле цикла.

Когда достигается конец потока, a становится null и цикл while завершается.

Эта идиома позволяет легко обрабатывать весь поток данных, будь то из всего файла, из всего соединения сокета или иным образом в целом чтение из всего входного потока данных. Он выглядит более сложным, чем простой while цикл, но это просто стандартный while цикл с более сложным условием.

person rgettman    schedule 24.03.2016
comment
Я делал несколько клиент-серверных приложений для общения через сокет. Это означает, что суть моего вопроса на самом деле связана с методом readLine (). Итак, этот цикл будет завершен, когда будет достигнут конец потока ... Но когда это произойдет? Когда поток закрыт? - person Seba; 25.03.2016
comment
Это сделает закрытие потока с другого конца сокета; закрытие самого сокета также закроет его потоки. - person rgettman; 25.03.2016
comment
По сути, этот цикл выполняется до тех пор, пока поток или сокет не будет закрыт. Он не прекращается, ничего не читается. Его не прекращают, пока поток не мертв? - person Seba; 25.03.2016
comment
Он не будет завершен, пока поток не будет закрыт (или пока не произойдет IOException). - person rgettman; 25.03.2016
comment
Я очень благодарен и в то же время приношу свои извинения. Я изучаю Java пару месяцев, и я провел небольшое исследование по этому вопросу, но здесь я нашел наиболее удовлетворительный ответ. - person Seba; 25.03.2016

Поскольку большинство потоков ввода-вывода считывают не все данные сразу, а побитно, назначение read () или readLine () как часть условия WHILE гарантирует, что блок WHILE будет продолжать цикл, когда входной поток считывает биты. по битам, пока не останется ничего для чтения (то есть все данные будут прочитаны).

person Christian Nwafor    schedule 09.12.2019