Не удается выйти из цикла while в Java при извлечении строк из BufferedReader - PullRequest
0 голосов
/ 13 мая 2011

Я пытаюсь прочитать строки из BufferedReader в Java с помощью цикла while.Он будет проходить через BufferedReader как следует, но когда он выйдет из цикла, он "заморозит" выполнение кода.Я пытался отладить код, но после выполнения цикла пропадает сигнал выполнения.Понятия не имею, что я делаю не так:

Фрагмент кода:

BufferedReader reader = new BufferedReader(new  InputStreamReader(yourSocket.getInputStream()));
String nextLine = null;

nextLine = reader.readLine();
while (nextLine != null){ //print all of input stream
    System.out.println(nextLine);
    nextLine = reader.readLine();
}

Я предполагал, что, когда в BufferedReader не осталось строк, переменная nextLine будет возвращать ноль и прерыватьпетля.Я попытался разорвать цикл вручную, но, похоже, он тоже не работает.Опять же, код будет печатать строки BufferedReader в порядке, но любой код, следующий за циклом while, не обязательно будет выполняться.

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

Спасибо, Пэт

Ответы [ 4 ]

2 голосов
/ 13 мая 2011

Чтение из сокетов является блокирующим вызовом. Ваша программа не знает, что другая сторона закончила запись в сокет. Как правило, вам придется использовать некоторые маркеры или информацию о размере, чтобы определить, что программа на другом конце закончила запись в сокет. Прочитав этот маркер, вы выходите из цикла. Это поведение отличается от чтения, скажем, файлов - когда вы достигаете конца файла, вы получаете нулевое значение при вызове метода readLine () и можете выйти, как в своем примере.

1 голос
/ 13 мая 2011

Проблема кажется в том, что ваш Reader обернут вокруг блокировки Socket, которая не будет указывать конец потока , пока узел не закроет соединение ( или ваша сторона закрывает соединение). Возможно, вы прочитали все, что доступно , но когда вы пытаетесь прочитать больше, базовые InputStream блокируют попытки прочитать больше данных из сокета.

Когда некоторые данные в конечном итоге становятся доступными, InputStream сделает эти данные доступными для Reader, и, как только Reader увидит достаточно, чтобы составить полную строку - или конец потока - вы получите последнюю строчку из Reader. Попытка прочитать следующую строку в итоге вернет ноль.

0 голосов
/ 18 ноября 2016

Я только что ответил на чужой пост об этом. Мой обманщик обходит это.

Использование цикла, как вы ...

String line;
while ((line = in.readLine()) != null) {
    System.out.println(line);
    sleep(in);
    if(!in.ready()){
        break;
    }
}

Есть способ обмана, который я понял.

private static void sleep(BufferedReader in) throws IOException {
    long time = System.currentTimeMillis();
    while(System.currentTimeMillis()-time < 1000){
        if(in.ready()){
            break;
        }
    }       
}

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

0 голосов
/ 02 ноября 2012

Написав какой-то похожий код для изучения того, как обрабатывать HTTP-запросы в Java, я не верю, что поведение BufferedReader совместимо с чтением из Socket, используемого для передачи HTTP-запросов, потому что, как уже упоминалось, readLine () блокирует, если больше нет данных для чтения, поэтому ваше приложение зависает. В соответствии со спецификацией HTTP клиент сохраняет Socket открытым после того, как он написал свой запрос, поэтому readLine () просто ждет, пока не станет доступно больше данных. Попытка обнаружить завершающий \ n \ r в последней строке HTTP-запроса также не работает в строке, возвращаемой readLine (), поскольку она удаляет любую комбинацию символов конца строки: \ n, \ r или \ r \ п.

Пустая строка также включена между заголовками и телом запроса, поэтому, если вы ищете пустую строку в качестве завершения сообщения, вам нужно проверить, что это не строка между заголовками и телом.

Я думаю, что для этого нужно читать посимвольное чтение из InputStream с read (byte []) - оно будет считываться до размера вашего байта [] и прекращает чтение, если встречается конец потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...