2010-12-15 8 views
11

Mam ten kod w Javie:Czytaj wiersz tekstu ze strumienia wejściowego w Javie utrzymując znak (ów) line-terminacji

InputStreamReader isr = new InputStreamReader(getInputStream()); 
BufferedReader ir = new BufferedReader(isr); 
String line; 
while ((line = ir.readLine()) != null) { 
//do stuff with "line" 
} 

Jeśli strumień wejściowy zawiera następujące elementy: „cześć \ nhey \ ryo \ r \ ngood-day”, a następnie zmienna linia byłaby po każdej iteracji:

  1. cześć
  2. hej
  3. yo
  4. dobry-da y

Chcę przeczytać jeden wiersz na raz, ale chcę zachować charakter line-terminacji (s):

  1. cześć \ n
  2. hej \ r
  3. yo \ r \ n
  4. dobry dzień

Jak mogę to zrobić? Czy mogę skorzystać z gotowych zajęć?

-

Aktualizacja:

Oto, co usiłuję zrobić i dlaczego muszę zachować charakter end-of-line (i dlaczego postać EOL może być inna).

Czytam żądanie POST. Składają się z czystych wiadomości tekstowych, w których wiersze zawsze kończą się \ r \ n (według standardowej specyfikacji). Jednak żądanie POST może zawierać dane binarne, które mogą zawierać bajty, które wyglądają jak znaki kończące na obiektach Java Reader.

W moim przykładzie trwa przesyłanie obrazu. Dane obrazu są wysyłane w jednym wierszu. Jednak dane binarne obrazu zawierają bajty, które CZYTNIK powinien interpretować jako "\ n", "\ r" lub czasami "\ r \ n", jeśli te dwa bajty znajdują się obok siebie.

Muszę przeczytać żądanie POST po jednej linii, ponieważ tak to działa. Przypuszczam, że mógłbym przeczytać wszystko, a następnie przeanalizować całość. Ale to nie jest wydajne, zwłaszcza jeśli przesyłany jest duży plik (na przykład 1024 MB).

+0

Jeśli nie możesz znaleźć lepszego rozwiązania, możesz zaimplementować 'readLine' używając' BufferedReader.read() 'w pętli' while'. – pts

+0

Miałem nadzieję, że ta bardzo podstawowa czynność została już wykonana, można by pomyśleć, że mogliby ją sformułować tak, aby metoda readLine() BufferedReadera przyjęła wartość boolowską - jeśli jest prawdziwa, to również zawierałaby znak (znaki) separatora linii i gdyby było fałszywe, zachowywałoby się tak, jak w tej chwili. – Mike

+0

Czy szczególny charakter końcowy jest ważny do zachowania? Ponieważ pierwszą rzeczą, o której pomyślałem, było właśnie dodanie '\ n' do linii – TheLQ

Odpowiedz

4

Jeśli chcesz przeczytać żądania HTTP POST, zdecydowanie sugerują, korzystając BufferedInputStream.read() (nie BufferedReader!) Bezpośrednio (bez readLine -jak abstrakcji pośrednich), zwracając uwagę na wszystkie szczegóły ręcznie, w tym postępowania z CR i LF według HTTP RFC.

Oto moja odpowiedź na bardziej szczegółowe pytanie (jak zaimplementować dokładnie to, readLine). To może nie być najszybszym rozwiązaniem, ale nadszedł czas, złożoność jest optymalne, a to działa:

import java.io.BufferedReader; 
import java.io.IOException; 
public class LineReader { 
    private int i = -2; 
    private BufferedReader br; 
    public OriginalLineReader(BufferedReader br) { this.br = br; } 
    public String readLine() throws IOException { 
    if (i == -2) i = br.read(); 
    if (i < 0) return null; 
    StringBuilder sb = new StringBuilder(); 
    sb.append((char)i); 
    if (i != '\r' && i != '\n') { 
     while (0 <= (i = br.read()) && i != '\r' && i != '\n') { 
     sb.append((char)i); 
     } 
     if (i < 0) return sb.toString(); 
     sb.append((char)i); 
    } 
    if (i == '\r') { 
     i = br.read(); 
     if (i != '\n') return sb.toString(); 
     sb.append((char)'\n'); 
    } 
    i = -2; 
    return sb.toString(); 
    } 
} 

Nie znajdziesz takiej readLine wbudowane w Javie. Prawdopodobnie znajdziesz podobnego, ale nie do końca pasującego readLine s w pliku innej firmy .jar. Moim zaleceniem jest użycie powyższego, jeśli naprawdę potrzebujesz tej funkcji.

+0

To jest właśnie ten kod, w którym miałem nadzieję, że nie będę musiał sam pisać, dziękuję bardzo! Wciąż myślę, że domyślnie powinno to być w Javie. – Mike

+1

Gdy te interfejsy API w języku Java zostały zaprojektowane pod kątem specyfiki dla platformy, kodowanie końca linii było jeszcze bardziej nieporęczne niż obecnie. Próbują Cię odizolować od konieczności radzenia sobie z \ n vs \ r vs \ r \ n vs Bóg wie tylko, jakie zastrzeżone * Nixes używał w 1993 roku, dostarczając readLine i writeLine i posługując się nim wewnętrznie. – Affe

+0

Affe: Myślę, że w twoim rozumowaniu występuje drobny błąd rzeczowy. Ogólnie rozumiem, że wszystkie systemy uniksowe zawsze miały "\ n" (co jest równe '10') jako terminator linii. – pts

Powiązane problemy