2010-03-23 4 views
2

У меня есть следующий пример чтения из буферного читателя:Как читать из буферизованного читателя?

while ((inputLine = input.readLine()) != null) { 
    System.out.println("I got a message from a client: " + inputLine); 
} 

Код в цикле println будет выполняться всякий раз, когда что-то появляется в забуференном читателе (input в данном случае). В моем случае, если клиент-приложение что-то пишет в сокет, будет выполнен код в цикле (в сервере-приложении).

Но я не понимаю, как это работает. inputLine = input.readLine() ждет, пока в буферизованном считывателе ничего не появится, и когда что-то появится там, оно вернет true и код в цикле будет выполнен. Но когда null может быть возвращен.

Существует еще один вопрос. Вышеприведенный код был взят из метода, который throws Exception, и я использую этот код в методе выполнения Thread. И когда я пытаюсь поставить throws Exception перед run, компилятор жалуется: переопределенный метод не генерирует исключение. Без throws exception у меня есть еще жалоба от компилятора: незарегистрированное исключение. Так что я могу сделать?

+0

@Roman - вы знаете сделку. Положите разные вопросы в разные вопросы! –

+0

Stephen C, я думал, что добавленная часть также была частью «как я должен читать из буферизованного читателя?». Но я вижу вашу точку зрения. Я удалил добавленную часть. – Roman

ответ

5

Когда розетка на другом конце закрыта, считыватель должен вернуть пустую строку. Это условие, которое вы ищете. Чтобы обработать исключение, заверните цикл чтения в блок try/catch.

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); 
} 

Вы можете найти эту tutorial на чтение/запись из/в сокет в Java, полезно.

0

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

О вашем втором вопросе, вы должны положить блок try/catch внутри метода, поймать Исключение и обработать его. Не перебрасывайте его.

1

Читатель readLine() вернет строковое значение, когда у него есть что-то прочитанное, пустая строка, когда ничего еще нет, и null, когда соединение закрыто.

Я бы рекомендовал обернуть попытку/уловить вокруг вашего блока кода с помощью функции ввода-вывода и обработать ошибки соответствующим образом.

0

Но я не понимаю, как это работает. .... ждет, пока что-то не появится в забуференном читателя и когда что-то появляется там он возвращает истинный

Нет, она возвращает значение выражения (inputLine = input.readLine()), сам inputLine , Значение InputLine сравнивается с NULL.

0

null возвращается, когда «EOF (конец файла)» достигнут. Поскольку это чтение из сетевого сокета, конец файла создается, когда сокет отключен (либо сервером, либо клиентом), но вы, скорее всего, получите исключение, прежде чем вы действительно увидите EOF.

0

Если это не домашнее задание, вы можете посмотреть Apache Commons IOUtils.

Предполагая, что вы не создают BufferedReader, и просто остановиться на InputStream:

String results = IOUtils.toString(inputStream); 
System.out.println(results); 
0
while ((inputLine = input.readLine()) != null) { 

Посмотрите на каждую часть выражения:

input.readLine() 

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

inputLine = input.readLine() 

Назначает эту строку inputLine

((inputLine = input.readLine()) != null) 

Проверяет, что строка, которая была назначена не является нулевым (конец потока).

3

Для вашего первого вопроса:

Но я не понимаю, как это работает. inputLine = input.readLine() ждет, пока в буферизованном считывателе ничего не появится, и когда что-то появится там, оно вернет true, и код в цикле будет выполнен. Но когда null может быть возвращен.

BufferedReader.readLine() не возвращается true после успеха. Он возвращает строку, содержащую прочитанную строку. Если конец потока достигнут, он возвращает null.

Ваш второй вопрос:

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

Вы должны обернуть свой код в try/catch block. Если вы не хотите обрабатывать исключенное исключение, просто оставьте эту деталь пустой (не рекомендуется)

try { 
    while ((inputLine = input.readLine()) != null) { 
     System.out.println("I got a message from a client: " + inputLine); 
    } 
} catch (Exception e) { 
    //handle exception 
} 
0

Вы получили хорошие ответы. Просто поймайте исключение и обработайте его локально. Если вам нужно передать это на другой код, но не может, поскольку метод run() не позволяет исключить проверку, вы можете обернуть исключение в некотором исключении RuntimeException. Если метод запуска выполняется непосредственно в потоке (так как это возможно Runnable), вам следует позаботиться о повторном броске обернутого исключения.

Что касается результата от readLine(), он вернет null, когда читать больше нечего. В случае сокета это происходит, когда другая сторона полностью закрывает сокет (любое внезапное завершение или нечистое закрытие обычно приводит к исключению в вашем коде, поскольку ОС отправляет другое уведомление о закрытии сокета).

У меня есть одно слово предостережения, так как вы обертываете розетку в java.io.BufferedReader. Вы должны быть очень осторожны при использовании этого в любом виде производственного кода.

Опасность состоит в том, что BufferedReader не справляется с исключениями в середине чтения. Это особенно важно, если вы включили тайм-аут в сокете, чтобы код автоматически получал периодические исключения из операционной системы. Тайм-аут (или другое исключение) может наступить, когда буфер внутри читателя заполняется. Если вы попытаетесь повторно использовать объект после исключения, он будет игнорировать любое предыдущее содержимое в буфере. Пакет (ы), которые были получены ранее, молча потеряны, и нет способа получить эти байты.

Обратите внимание, что существуют и другие виды исключений сокетов, которые не означают, что сокет был утерян. Например, посмотрите на определение java.io.InterruptedIOException. Это имеет общедоступную переменную, которая сообщает количество успешно переданных байт в последнем запросе ввода/вывода (чтение или запись). Это означает, что операция ввода-вывода может быть выполнена снова для извлечения или отправки оставшихся байтов для пакета.

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^