BufferedReader не сообщает «готово», когда должно - PullRequest
8 голосов
/ 21 января 2011

Я пытаюсь прочитать текст из веб-документа, используя BufferedReader через InputStreamReader по URL (в файл на каком-либо сервере Apache).

String result = "";
URL url = new URL("http://someserver.domain/somefile");
BufferedReader in = null;
in = new BufferedReader(new InputStreamReader(url.openStream(), "iso-8859-1"));

result += in.readLine();

Теперь это работает просто отлично. Но, очевидно, я бы хотел, чтобы читатель читал не одну строку, а столько, сколько в файле.
Глядя на API BufferedReader, следующий код должен сделать именно это:

while (in.ready()) {
    result += in.readLine();
}

т.е. читать все строки, пока строк больше, останавливаться, когда строк больше нет. Однако этот код не работает - читатель просто никогда сообщает ready () = true !

Я могу даже напечатать значение ready () прямо перед чтением строки (которая читает правильную строку из файла), но читатель сообщит « false ».

Я что-то не так делаю? Почему BufferedReader возвращает ' false ' в состоянии готовности, когда есть что прочитать?

Ответы [ 7 ]

9 голосов
/ 21 января 2011

ready ()! = Имеет больше

ready() не означает, что есть еще данные для чтения.Он показывает только, может ли чтение заблокировать поток .Вполне вероятно, что он вернет false до того, как вы прочитаете все данные.

Чтобы выяснить, нет ли больше данных, проверьте, возвращает ли readLine() null.

String line = in.readLine();
while(line != null){
   ...
   line = in.readLine();
}
6 голосов
/ 21 января 2011

Другой способ сделать это, обходя in.ready(), выглядит примерно так:

while ((nextLine = in.readLine()) != null) {
  result += nextLine;
}

Вы просто продолжите читать, пока не закончите. Таким образом, вам не нужно беспокоиться о проблеме с in.ready().

3 голосов
/ 21 января 2011

Я думаю, что стандартный способ написать это - просто попытаться прочитать строку и убедиться, что она когда-нибудь вернулась. Примерно так:

while ((String nextLine = in.readLine()) != null) {
    //System.out.println(nextLine);
    result += nextLine;
}

Так что вы просто продолжаете идти, пока не получите нуль, возвращенный из потока. Смотрите здесь для дополнительной информации:

http://download.oracle.com/javase/1.5.0/docs/api/java/io/BufferedReader.html#readLine()

2 голосов
/ 21 января 2011

Метод BufferedReader.ready() работает как указано:

Reader.ready() javadoc говорит следующее:

[Возвращает] true, если следующий read() гарантированно не заблокирован для ввода, false в противном случае. Обратите внимание, что возврат false не гарантирует блокировку следующего чтения.

Тогда BufferedReader.ready() javadoc говорит следующее:

Сообщает, готов ли этот поток для чтения. Буферизованный символьный поток готов, если буфер не пуст, или если базовый символьный поток готов .

Если сложить эти два значения вместе, становится ясно, что BufferedReader.ready() может вернуть false в ситуациях, когда доступны символы. Короче говоря, вы не должны полагаться на ready() для проверки логического конца файла или конца потока.

0 голосов
/ 26 января 2017

Если вы хотите использовать in.ready (), у меня хорошо сработало следующее:

    for (int i = 0; i < 10; i++) {
        System.out.println("is InputStreamReader ready: " + in.ready());
        if (!in.ready()) {
            Thread.sleep(1000);
        } else {
            break;
        }
    }
0 голосов
/ 19 июля 2011

В основном метод BufferedReader.ready () можно использовать для проверки того, готов ли базовый поток для предоставления данных вызывающей стороне метода ... иначе мы можем подождать поток некоторое время, пока он не станет готовым.

Но реальная проблема заключается в том, что после того, как мы полностью прочитаем поток данных, он выдаст false .. поэтому мы не знали, является ли поток полностью прочитанным ИЛИ основной поток занят ....

0 голосов
/ 21 января 2011

Это то, что мы использовали последовательно в течение многих лет - не уверен, что это «стандартный» метод. Я хотел бы услышать комментарии о плюсах и минусах использования URL.openURLStream () напрямую, и если это вызывает проблемы OP Этот код работает как для HTTP, так и для HTTPS соединений.

 URL  getURL = new URL (servletURL.toString() + identifier+"?"+key+"="+value);      
 URLConnection uConn = getURL.openConnection();

 BufferedReader br = new BufferedReader (new
                            InputStreamReader (uConn.getInputStream()));
 for (String s = br.readLine() ; s != null ; s = br.readLine()) {
      System.out.println ("[ServletOut] " + s);
      // do stuff with s
 }               
 br.close();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...