2015-03-11 1 views
14

Je veux taper un texte multiligne dans la console en utilisant un BufferedReader et quand j'appuie sur "Entrée" pour trouver la somme de la longueur du texte entier. Le problème est qu'il semble que je suis dans une boucle infinie et quand j'appuie sur "Enter" le programme ne se termine pas. Mon code est ci-dessous:Lire toutes les lignes avec 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(); 
    } 

Pourriez-vous s'il vous plaît me dire ce que je fais mal?

+4

lorsque vous n'appuyez sur Entrée 'sera égal coût média "" non nul. essayez de changer 'line! = null' à'! line.equals ("") ' – StephenButtolph

+3

Aussi, juste pour fournir d'autres opinions (par exemple en utilisant une boucle for), http://codereview.stackexchange.com/questions/44135/ is-it-ok-to-use-while-line-r-readline-null-construct – Foon

+0

J'ai réalisé hier soir que je m'endormais: pour quoi utilisez-vous la longueur? NB que si vous deviez faire un chat myfile | Java yourprogram et imprimer la valeur de la longueur, ce sera en désaccord avec ce que, par exemple. wc imprime parce que vous ne comptez pas les nouvelles lignes. Si vous avez besoin de faire cela, notez que les fichiers DOS auront "\ r \ n" et les fichiers UNIX auront "\ n" et ma suggestion originale d'utiliser System.getProperty ("line.separator") ne fonctionnera probablement pas parce que il n'y a aucune garantie que vous n'êtes pas essayer de lire un fichier DOS sous Linux. (Donc, j'espère que ce n'est pas ce que vous voulez faire) – Foon

Répondre

19

La façon idiomatiques de lire toutes les lignes est while ((line = buffer.readLine()) != null). Aussi, je suggère un try-with-resources statement.Quelque chose comme

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

Si vous voulez mettre fin à la boucle lorsque vous recevez une ligne vide, ajoutez un test que dans la boucle while

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

JLS-14.15. The break Statement dit

Une déclaration break transfère le contrôle d'une instruction englobante.

+0

Parce que l'OP est en train de lire 'system.in', cela ne s'arrêtera-t-il jamais? contribution? – StephenButtolph

+1

@StephenB Il se terminera sur EOF (ou ctrl-d); éventuellement aussi avec ctrl-c et/ou ctrl-brk. –

+2

Mais je pense qu'il veut qu'il se termine quand il appuie sur Entrée. – StephenButtolph

3

line ne sera pas nulle lorsque vous appuyez sur Entrée; Ce sera une chaîne vide.

Prenez note de ce que l'BufferedReader JavaDoc dit au sujet readLine():

Reads une ligne de texte. Une ligne est considérée comme terminée par un saut de ligne ('\ n'), un retour chariot ('\ r') ou un retour chariot suivi immédiatement d'un saut de ligne.

Et readLine() rendements:

une chaîne contenant le contenu de la ligne, sans compter tous les caractères de fin de lignes, ou une valeur nulle si la fin du flux est atteinte

Ainsi, lorsque vous appuyez sur [Entrée], vous donnez au BufferedReader une nouvelle ligne contenant uniquement \n, \r ou \r\n. Cela signifie que readLine() renverra une chaîne vide.

Donc, essayez quelque chose comme ceci:

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

J'ai peut-être tort. Mais je ne pense pas que la chaîne renvoyée contienne réellement le caractère de fin de ligne. Si c'est le cas, alors un System.out.println (buffer.readLine()); 'aurait une autre ligne à la fin, à droite? – StephenButtolph

+2

Toujours dans JavaDoc vous avez lié à: * "renvoie [...] le contenu de la ligne, n'incluant aucun caractère de fin de ligne" *. – Radiodef

+0

@StephenB et @RadioDef: Ah mon erreur! Vous avez tous les deux raison. J'ai été confondu avec 'read()' et qui sait quoi. – dbank

0

réponse Snarky: ce que vous faites mal crée seulement 2 objets Java pour faire quelque chose ... si vous cherchez, vous pouvez probablement trouver quelques plus de classes qui étendent BufferedReader ou ExtendedBufferReader etc, et puis il peut être vrai Enterprise Java.

Maintenant que je l'ai sorti de mon système: réponse plus utile. System.in est fermé lorsque vous entrez EOF, qui est Control-D sous Linux et je pense que MacOS, et je pense Control-Z plus entrer sous Windows. Si vous voulez vérifier pour entrer (ou plus précisément, deux entre ... un pour terminer la dernière ligne et un pour indiquer que vous avez terminé, qui est essentiellement la façon dont http gère la détermination lorsque les en-têtes http sont terminés et il est temps pour le corps de http, alors la solution de @dbank devrait être une option viable avec une correction mineure que je vais essayer de faire pour déplacer le! dedans du prédicat while au lieu de! while

(Edit # 2: réalisé readLine supprime la nouvelle ligne, donc une ligne vide remplacerait la nouvelle ligne par "", et maintenant mon code passe à une autre réponse avec le bit EOF comme réponse à la place du commentaire

Éditez ... c'est bizarre, @dbank avait J'ai répondu pendant que je tapais ma réponse, et je me serais arrêté si je n'avais pas mentionné l'alternative EOF. de la mémoire avec l'édition que j'allait faire:

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

Pour l'électeur (s) vers le bas: si c'était à cause de la réponse snarky en haut, byte moi (je veux dire, nouveau Byte [] ("moi" .getBytes (Charset.forName ("UTF-8"))) Sinon, je suis curieux de savoir pourquoi les downvotes: Mon code est similaire à d'autres (et quand j'ai posté la réponse de @ dbank est apparu, a disparu, et maintenant réapparu, vous ne pouvez pas le voir maintenant à la marque de 9 heures, mais ma réponse était Posté marginalement avant les autres) et je mentionne aussi l'option EOF (qui est aussi utile lors de la tuyauterie) – Foon

3

Lorsque vous appuyez uniquement sur Entrée, le retour de buffer.readLine(); n'est pas nul, il s'agit d'une chaîne vide.

Par conséquent, vous devriez changer line != null à !line.equals("") (Vous pouvez également changer à line.length() > 0)

Maintenant, votre code ressemblera à quelque chose comme ceci:

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

line = buffer.readLine(); 

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

Cela devrait résoudre votre problème. J'espère que cela a aidé! :)

+0

Cela fonctionne en effet, mais pour une raison quelconque, je dois appuyer sur Entrée deux fois. Une idée de pourquoi c'est? – deadpixels

+0

@deadpixels Lorsque j'exécute le programme, il se termine à la première ligne vide. Le compteur augmente-t-il lorsque vous appuyez sur Entrée? – StephenButtolph

0

Depuis Java 8, vous pouvez utiliser la méthode BufferedReader#lines directement sur un lecteur tamponné.

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

Une ligne de code Java en utilisant 8:

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