2015-03-11 27 views
14

Voglio digitare un testo a più righe nella console utilizzando un BufferedReader e quando premo "Invio" per trovare la somma della lunghezza dell'intero testo. Il problema è che sembra che sto entrando in un ciclo infinito e quando premo "Invio" il programma non termina. Il mio codice è qui sotto:Leggi tutte le righe con BufferedReader

InputStreamReader instream = new InputStreamReader(System.in); 
BufferedReader buffer = new BufferedReader(instream); 

    line= buffer.readLine(); 

    while (line!=null){ 
     length = length + line.length(); 
     line= buffer.readLine(); 
    } 

Potrebbe dirmi cosa sto facendo male?

+4

quando si preme solo entrare 'Line' sarà uguale a "" non nullo. prova a cambiare 'line! = null' in'! line.equals ("") ' – StephenButtolph

+3

Inoltre, solo per fornire alcuni altri pareri (es. usando un ciclo for), http://codereview.stackexchange.com/questions/44135/ is-it-ok-to-use-while-line-r-readline-null-construct – Foon

+0

Mi sono reso conto ieri sera mentre mi stavo addormentando: per cosa stai usando la lunghezza? NB che se tu dovessi fare cat myfile | java yourprogram e stampa il valore della lunghezza, questo non sarà d'accordo con cosa, ad es. wc stampa fuori, perché non stai contando i newline. Se hai bisogno di farlo, nota che i file DOS avranno "\ r \ n" e che i file UNIX avranno "\ n" e il mio suggerimento originale di usare System.getProperty ("line.separator") probabilmente non funzionerà perché non c'è garanzia che tu non sia eg cercando di leggere un file DOS sotto Linux. (Quindi, spero che non sia quello che sei cattivo da fare) – Foon

risposta

19

Il modo idiomatico di leggere tutte le linee è while ((line = buffer.readLine()) != null). Inoltre, suggerirei un try-with-resources statement.Qualcosa di simile

try (InputStreamReader instream = new InputStreamReader(System.in); 
     BufferedReader buffer = new BufferedReader(instream)) { 
    long length = 0; 
    String line; 
    while ((line = buffer.readLine()) != null) { 
     length += line.length(); 
    } 
    System.out.println("Read length: " + length); 
} catch (Exception e) { 
    e.printStackTrace(); 
} 

Se si desidera terminare il ciclo quando si riceve una riga vuota, aggiungere un test per che nel while ciclo

while ((line = buffer.readLine()) != null) { 
    if (line.isEmpty()) { 
     break; 
    } 
    length += line.length(); 
} 

JLS-14.15. The break Statement dice

A break dichiarazione trasferisce il controllo da una dichiarazione allegata.

+0

Poiché l'OP sta leggendo da 'system.in' questo non finirà mai? Non sarebbe solo aspettare gli utenti ingresso? – StephenButtolph

+1

@StephenB Si concluderà su EOF (o ctrl-d); possibilmente anche con ctrl-c e/o ctrl-brk. –

+2

Ma penso che voglia che finisca quando preme Invio. – StephenButtolph

3

line non sarà nullo quando si preme invio; sarà una stringa vuota vuota.

prendere atto di ciò il BufferedReader JavaDoc dice di readLine():

Legge una riga di testo. Una riga viene considerata terminata da uno qualsiasi di un avanzamento riga ('\ n'), un ritorno a capo ('\ r') o un ritorno a capo seguito immediatamente da un avanzamento riga.

E readLine() rendimenti:

una stringa contenente il contenuto della riga, ad esclusione di tutti i caratteri line-terminazione, o null se la fine del flusso è stata raggiunta

Quindi, quando premi [Invio], stai dando alla BufferedReader una nuova riga contenente solo \n, \r o \r\n. Ciò significa che readLine() restituirà una stringa vuota.

Quindi provare qualcosa di simile, invece:

InputStreamReader instream = new InputStreamReader(System.in); 
BufferedReader buffer = new BufferedReader(instream); 

line = buffer.readLine(); 

while((line != null) && (!line.isEmpty())){ 
    length = length + line.length(); 
    line = buffer.readLine(); 
} 
+2

Potrei sbagliarmi. Ma non penso che la stringa restituita contenga effettivamente il carattere di fine riga. Se facesse allora un 'System.out.println (buffer.readLine());' avrebbe un'altra riga alla fine, giusto? – StephenButtolph

+2

Anche nel JavaDoc è stato eseguito il collegamento a: * "restituisce [...] il contenuto della riga, escluso qualsiasi carattere di terminazione di riga" *. – Radiodef

+0

@StephenB e @RadioDef: Ah, mio ​​errore! Hai entrambi ragione. Ero confuso con 'read()' e chissà cosa. – dbank

0

risposta Snarky: quello che stai facendo male è la creazione di solo 2 oggetti in Java per fare qualcosa ... se si cerca, si può probabilmente trovare alcuni più classi che estendono BufferedReader o ExtendedBufferReader ecc. e quindi può essere Enterprise Java reale.

Ora che ho ottenuto dal mio sistema: risposta più utile. System.in viene chiuso quando si inserisce EOF, che è Control-D in Linux e penso che MacOS e I credano in Control-Z e in Windows. Se vuoi controllare per entrare (o più specificatamente, due entrano ... uno per finire l'ultima riga e uno per indicare che hai finito, che è essenzialmente come http gestisce la determinazione quando le intestazioni http sono finite ed è ora di il corpo http, quindi la soluzione di @dbank dovrebbe essere un'opzione praticabile con una correzione minore che cercherò di fare per spostare il predicato while al posto di! while.

(Modifica n. 2: realizzato readLine rimuove la newline, quindi una riga vuota "" invece di una nuova riga, quindi ora il mio codice devolve ad un'altra risposta con il bit EOF come risposta invece del commento)

Modifica ... è strano, @dbank aveva rispose mentre stavo scrivendo la mia risposta, e mi sarei fermato se non avessi menzionato l'alternativa EOF. de dalla memoria con la modifica che stava per fare:

InputStreamReader instream = new InputStreamReader(System.in); 
BufferedReader buffer = new BufferedReader(instream); 

    line= buffer.readLine(); 
    while (line != null && !line.equals("")){ 
     length = length + line.length(); 
     line= buffer.readLine(); 
    } 
+0

Per gli elettori in basso: se questo fosse dovuto alla risposta snarky in alto, byte me (intendo, new Byte [] ("me" .getBytes (Charset.forName ("UTF-8")))) Altrimenti, sono curioso di sapere perché i downvotes: il mio codice è simile ad altri (e quando ho postato la risposta di @bank è scomparsa, e ora è ricomparsa, non puoi vederla ora al momento delle 9 ore, ma la mia risposta è stata postato marginalmente prima degli altri) e menziono anche l'opzione EOF (che è utile anche per le connessioni) – Foon

3

Quando si preme Invio, il ritorno da buffer.readLine(); non è nullo, è una stringa vuota.

Pertanto si dovrebbe cambiare line != null a !line.equals("") (Si potrebbe anche cambiare a line.length() > 0)

Ora il codice sarà simile a questa:

InputStreamReader instream = new InputStreamReader(System.in); 
BufferedReader buffer = new BufferedReader(instream); 

line = buffer.readLine(); 

while (!line.equals("")){ 
    length = length + line.length(); 
    line = buffer.readLine(); 
} 

Questo dovrebbe risolvere il problema. Spero che questo ha aiutato! :)

+0

Funziona davvero, ma per qualche motivo devo premere Invio due volte. Qualche idea del perché? – deadpixels

+0

@deadpixels Quando eseguo il programma termina alla prima riga vuota. Il contatore si alza quando premi Invio? – StephenButtolph

0

Poiché Java 8 è possibile utilizzare il metodo BufferedReader#lines direttamente sul lettore bufferizzato.

try (InputStreamReader in = new InputStreamReader(System.in); 
     BufferedReader buffer = new BufferedReader(in)) { 
     final int length = buffer.lines().mapToInt(String::length).sum(); 
     System.out.println("Read length: " + length); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
28

Una linea di codice utilizzando Java 8:

line = buffer.lines().collect(Collectors.joining());