2011-01-21 2 views
5

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

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

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

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

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

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

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

+0

Я не знаю, имеет ли это значение, но URL-адрес фактически указывает на местоположение с использованием HTTPS. Однако сертификаты устанавливаются правильно на сервере и на машине, на которой выполняется вышеуказанный код. Также readLine() возвращает первую строку без проблем. – fgysin

+0

Он будет готов, когда есть ожидающие данные, однако у него не будет ожидающих данных, пока вы не выполните чтение/чтение. Даже если есть ожидание данных, это может быть не полная строка, поэтому readLine() будет блокировать в любом случае. –

+0

Lotta отличные ответы, thx каждый. К сожалению, я могу отметить только один признанный ответ. :) – fgysin

ответ

7

готов()! = Имеет более

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

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

String line = in.readLine(); 
while(line != null){ 
    ... 
    line = in.readLine(); 
} 
4

Другим способом вы можете сделать это, что минует in.ready() что-то вроде:

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

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

+0

Я думаю, что вы подорвали свой ответ, сделав его похожим на обходное решение. То, что вы показали, является наиболее распространенной идиомой для чтения из BufferedReader, но что более важно, это правильно. Использование метода 'ready()', аналогичного OP, является ** не ** правильным. –

3

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

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

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

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

+0

Извините, я не должен говорить «стандартный» способ, а скорее то, что я видел чаще всего. –

+0

Также - не забудьте использовать StringBuffer при построении больших строк (или StringBuilder для несинхронизированных операций): http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ StringBuffer.html –

+2

Нет, это довольно стандартно, хотя это неверно Java ('String' вместо' string', и это объявление должно быть вне выражения). Идиомой, которую я использую, является 'for (String l = null; (l = in.readLine())! = Null;) {' –

2

Метод BufferedReader.ready() ведет себя, как указано:

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

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

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

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

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

0

Это то, что мы используем последовательно в течение многих лет - не уверен, что это «стандартный» метод. Я хотел бы услышать комментарии о плюсах и минусах использования 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(); 
0

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

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

+0

Добро пожаловать в StackOverflow. Пожалуйста, не забудьте проверить, как использовать форматирование [Markdown] (http://en.wikipedia.org/wiki/Markdown). Это сделает ваши ответы более полезными для других. – marko

0

Если вы хотите использовать 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; 
     } 
    } 
Смежные вопросы