2011-01-21 7 views
5

Próbuję odczytać tekst z dokumentu internetowego za pomocą BufferedReader przez InputStreamReader pod adresem URL (do pliku na serwerze Apache).Buforowany czytnik nie podał "gotowości", gdy powinien:

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

Teraz działa dobrze. Ale oczywiście chciałbym, żeby czytelnik nie przeczytał tylko jednej linii, ale tyle, ile jest w pliku.
Patrząc na API BufferedReader następujący kod powinien zrobić tylko, że:

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

Tj przeczytaj wszystkie linie, gdy jest więcej linii, zatrzymaj się, gdy nie ma już linii. Ten kod nie działa jednak - czytnik tylko nigdy raportów ready() = true!

Mogę nawet wydrukować wartość ready() tuż przed odczytaniem linii (która odczytuje poprawny ciąg z pliku), ale czytnik zgłosi "false".

Czy robię coś nie tak? Dlaczego BufferedReader zwraca "fałsz" w stanie gotowym, gdy rzeczywiście jest coś do odczytania?

+0

Nie wiem, czy to ma znaczenie, ale adres URL faktycznie wskazuje na lokalizację za pomocą HTTPS. Certyfikaty są jednak poprawnie zainstalowane na serwerze i na komputerze, na którym działa powyższy kod. Również readLine() zwraca pierwszą linię bez problemów. – fgysin

+0

Będzie on gotowy, gdy będą dane oczekujące, ale nie będzie miał danych oczekujących, dopóki nie wykonasz odczytu/readLine. Nawet jeśli są dane oczekujące, może to nie być kompletna linia, tak więc readLine() i tak się zablokuje. –

+0

Lotta wspaniałe odpowiedzi, thx każdy. Niestety mogę tylko oznaczyć jedną jako zaakceptowaną odpowiedź. :) – fgysin

Odpowiedz

7

ready()! = Ma więcej

ready() nie oznacza, że ​​nie ma więcej danych do odczytu. Pokazuje tylko, czy przeczytany może może zablokować wątek. Jest prawdopodobne, że zwróci false, zanim przeczytasz wszystkie dane.

Aby dowiedzieć się, czy nie ma więcej danych, sprawdź, czy readLine() zwraca null.

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

Innym sposobem można to, że omija in.ready() zrobić coś jak:

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

Będziesz tylko czytać dalej, aż skończysz. W ten sposób nie musisz martwić się o problem z in.ready().

+0

Myślę, że podważyłeś swoją odpowiedź, sprawiając, że brzmi to jak obejście. To, co pokazano, jest najczęstszym idiomem do czytania z BufferedReader, ale co ważniejsze, jest poprawne. Użycie metody 'ready()' takiej jak OP nie było ** nie ** poprawne. –

3

Myślę, że standardowym sposobem, aby to napisać, jest po prostu próba odczytania linii i zweryfikowania jej zwrotu. Coś takiego:

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

Po prostu kontynuuj, dopóki nie otrzymasz wartości null ze strumienia. Patrz tutaj dla dodatkowych informacji:

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

+0

Niestety, nie powinienem mówić "standardowy" sposób, ale raczej sposób, jaki widziałem najczęściej. –

+0

Również - nie zapomnij użyć StringBuffer podczas konstruowania dużych ciągów (lub StringBuilder dla niezsynchronizowanych operacji): http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ StringBuffer.html –

+2

Nie, to dość standardowe, chociaż nie jest to poprawna Java ('String' zamiast' string', a ta deklaracja musi znajdować się poza wyrażeniem). Idiomem, którego używam, jest 'for (String l = null; (l = in.readLine())! = Null;) {' –

2

Sposób BufferedReader.ready() zachowuje się jak określono:

Reader.ready() javadoc mówi co następuje:

[Powrót] true jeśli nie jest gwarantowana następnego read() blokować dane wejściowe, w innym przypadku false. Zwróć uwagę, że zwracanie false nie gwarantuje, że następny odczyt zostanie zablokowany.

Następnie BufferedReader.ready() javadoc mówi co następuje:

Informuje, czy strumień jest gotowy do odczytu. Buforowany strumień znaków jest gotowy, jeśli bufor nie jest pusty, lub jeśli podstawowy strumień znaków jest gotowy.

Jeśli umieścisz te dwa razem, to jest oczywiste, że BufferedReader.ready()może powrót false w sytuacjach, w których są dostępne znaki. Krótko mówiąc, nie należy polegać na ready(), aby przetestować logiczny koniec pliku lub koniec strumienia.

0

to co używamy konsekwentnie przez lata - nie wiem, czy to jest „standardowy” sposób. Chciałbym usłyszeć komentarze na temat zalet i wad używania URL.openURLStream() bezpośrednio, a jeśli to powoduje problemy PO. Ten kod działa zarówno dla połączeń HTTP, jak i 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

Zasadniczo BufferedReader.ready() metoda może być stosowana do sprawdzania, czy strumień bazowy jest gotowy do dostarczania danych do metody rozmówcy .... jeszcze możemy czekać nitkę przez jakiś czas, aż staje się gotowy .

Ale prawdziwym problemem jest to, że po tym jak całkowicie odczytać strumienia danych, będzie rzucać fałszywe .. więc nie wiem, czy strumień jest w pełni odczytać lub strumień bazowy jest zajęty ....

+0

Witamy w StackOverflow. Pamiętaj, aby sprawdzić, jak używać formatowania [Markdown] (http://en.wikipedia.org/wiki/Markdown). Sprawi, że twoje odpowiedzi będą bardziej użyteczne dla innych. – marko

0

Jeśli chcesz użyć in.ready(), dla mnie dobrze działało:

for (int i = 0; i < 10; i++) { 
     System.out.println("is InputStreamReader ready: " + in.ready()); 
     if (!in.ready()) { 
      Thread.sleep(1000); 
     } else { 
      break; 
     } 
    } 
Powiązane problemy