2015-03-11 14 views
14

Ich möchte einen mehrzeiligen Text in die Konsole mit einem BufferedReader eingeben und wenn ich "Enter" drücken, um die Summe der Länge des gesamten Textes zu finden. Das Problem ist, dass es scheint, dass ich in eine Endlosschleife komme und wenn ich "Enter" drücke, kommt das Programm nicht zu einem Ende. Mein Code ist unten:Lesen Sie alle Zeilen mit 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(); 
    } 

Könnten Sie mir bitte sagen, was ich falsch mache?

+4

, wenn Sie nur die Eingabetaste drücken 'line' wird gleich "" nicht null. Versuchen Sie, 'line! = null 'in'! line.equals ("") '' – StephenButtolph

+3

zu ändern, um weitere Meinungen zu geben (zB über eine for-Schleife), http://codereview.stackexchange.com/questions/44135/ is-it-ok-to-use-während-line-r-readline-null-construct – Foon

+0

realisierte ich letzte Nacht, als ich einschlief: Wofür verwenden Sie Länge? Achtung, wenn Sie cat myfile | Java Ihr Programm und drucken Sie den Wert der Länge aus, dies wird mit dem widersprechen, z. wc wird ausgedruckt, weil Sie keine Zeilenumbrüche zählen. Wenn Sie dies tun müssen, beachten Sie, dass DOS-Dateien "\ r \ n" haben und UNIX-Dateien "\ n" haben und mein ursprünglicher Vorschlag, System.getProperty ("line.separator") zu verwenden, wird wahrscheinlich nicht funktionieren Es gibt keine Garantie, dass Sie nicht z versuchen, eine DOS-Datei unter Linux zu lesen. (Also, hoffentlich ist das nicht das, was du tun willst) – Foon

Antwort

19

Die idiomatische Weise alle Zeilen zu lesen ist while ((line = buffer.readLine()) != null). Außerdem würde ich eine try-with-resources statement vorschlagen.So etwas wie

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

Wenn Sie die Schleife enden soll, wenn Sie eine leere Zeile erhalten, fügen Sie einen Test für das in der while Schleife

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

JLS-14.15. The break Statement sagt

A break Aussage Übergibt die Kontrolle aus einer umschließenden Anweisung.

+0

Weil das OP liest von 'system.in' wird das nicht nie enden? Würde es nicht nur auf die Benutzer als nächstes warten Eingang? – StephenButtolph

+1

@StephenB Es endet am EOF (oder ctrl-d); möglicherweise auch mit ctrl-c und/oder ctrl-brk. –

+2

Aber ich denke, er will, dass es aufhört, wenn er Enter drückt. – StephenButtolph

3

line wird nicht null sein, wenn Sie die Eingabetaste drücken; Es wird eine leere Zeichenfolge sein.

Beachten Sie, was die BufferedReader JavaDoc sagt über readLine():

Liest eine Textzeile. Eine Zeile wird entweder durch einen Zeilenvorschub ('\ n'), einen Wagenrücklauf ('\ r') oder einen Zeilenumbruch gefolgt von einem Zeilenvorschub beendet.

Und readLine() Rückkehr:

Ein String, den Inhalt der Zeile enthält, nicht einschließlich der linien Endzeichen oder null, wenn das Ende des Stroms wurde

erreicht

Wenn Sie also [Enter] drücken, geben Sie BufferedReader eine neue Zeile mit nur \n, \r oder \r\n an. Dies bedeutet, dass readLine() eine leere Zeichenfolge zurückgibt.

So versuchen, so etwas wie dieses stattdessen:

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

Ich könnte mich irren. Aber ich glaube nicht, dass der zurückgegebene String tatsächlich das Endzeilenzeichen enthält. Wenn es dann eine 'System.out.println (buffer.readLine());' hätte eine andere Zeile am Ende rechts? – StephenButtolph

+2

Auch in der JavaDoc, mit der Sie verlinkt haben: * "gibt den Inhalt der Zeile zurück, ohne irgendwelche Zeilenbeendigungszeichen" *. – Radiodef

+0

@StephenB und @RadioDef: Ah mein Fehler! Sie haben beide recht. Ich war verwirrt mit 'read()' und wer weiß was. – dbank

0

Snarky Antwort: was Sie falsch machen nur 2 Objekte in Java zu schaffen, etwas zu tun ... wenn Sie suchen, können Sie wahrscheinlich ein paar finden mehr Klassen, die BufferedReader oder ExtendedBufferReader usw. erweitern, und dann kann es sich um echtes Enterprise Java handeln.

Jetzt, dass ich das aus meinem System habe: nützlichere Antwort. System.in ist geschlossen, wenn Sie EOF eingeben, das ist Control-D unter Linux und ich denke, MacOS, und ich denken Control-Z plus unter Windows eingeben. Wenn Sie nach "Enter" suchen möchten (oder genauer, zwei gibt ... ein, um die letzte Zeile zu beenden, und eine, um anzuzeigen, dass Sie fertig sind der http Körper, dann @ dbank Lösung sollte eine praktikable Option mit einem kleinen Fix Ich werde versuchen zu machen, um die! innerhalb der während Prädikat anstelle von! while.

(Edit # 2: realisiert readLine streift den Zeilenumbruch, so dass eine leere Zeile "" anstelle des Zeilenumbruchs wäre, also geht mein Code zu einer anderen Antwort mit dem EOF-Bit als Antwort statt Kommentar.

Edit ... das ist komisch, @dbank hatte antwortete, während ich meine Antwort tippte, und ich hätte aufgehört, hätte ich die EOF-Alternative nicht erwähnt de aus dem Speicher mit dem bearbeiten wollte ich machen:

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

An den Down-Voter (n): wenn dies wegen der snarky Antwort an der Spitze war, Byte me (ich meine, neues Byte [] ("mich" .getBytes (Charset.forName ("UTF-8"))) Ansonsten bin ich neugierig, warum die downvotes: Mein Code ist ähnlich wie bei anderen (und als ich die @ dbank-Antwort veröffentlicht habe, verschwand, und jetzt wieder aufgetaucht; Sie können es jetzt nicht bei der 9-Stunden-Marke sehen, aber meine Antwort war gepostet vor den anderen) und ich erwähne auch die EOF-Option (die auch beim Piping nützlich ist) – Foon

3

Wenn Sie nur Enter drücken, ist die Rückgabe von buffer.readLine(); nicht null, es ist ein leerer String.

Deshalb sollten Sie line != null zu !line.equals("") ändern (Sie auch zu line.length() > 0 ändern könnte)

Jetzt Ihren Code so etwas wie folgt aussehen:

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

line = buffer.readLine(); 

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

Dieses Ihr Problem lösen sollte. Hoffe das hat geholfen! :)

+0

Das funktioniert zwar, aber aus irgendeinem Grund muss ich zweimal Enter drücken. Irgendeine Idee warum das ist? – deadpixels

+0

@deadpixels Wenn ich das Programm starte, endet es an der ersten leeren Zeile. Geht der Zähler nach oben, wenn Sie die Eingabetaste drücken? – StephenButtolph

0

Seit Java 8 können Sie BufferedReader#lines Methode direkt auf gepufferten Leser verwenden.

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

eine Zeile Code mit Java 8:

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