61 votes

Pourquoi hasNext() est faux, mais hasNextLine() est vrai ?

Question

Comment se fait-il que pour un objet scanner, le hasNextLine() renvoie un résultat positif alors que la méthode hasNext() renvoie un faux ?

Note : Sur la base du fichier d'entrée, le hasNext() renvoie le résultat comme prévu ; la méthode hasNextLine() ne semble pas renvoyer le bon résultat.

Code

Voici le code que j'exécute et qui donne les résultats ci-dessous :

public void ScannerTest(Reader fileReaderObject){
    Scanner scannerObj = new Scanner(fileReaderObject);

    for(int i = 1; scannerObj.hasNext(); i++){
        System.out.println(i + ": " + scannerObj.next());
        System.out.println("Has next line: " + scannerObj.hasNextLine());
        System.out.println("Has next: " + scannerObj.hasNext());
    }
    System.out.println();

    scannerObj.close();
}

Fichier d'entrée

Voici le contenu réel du fichier que je transmets à cet analyseur :

a   3   9
b   3   6
c   3   3
d   2   8
e   2   5
f   2   2
g   1   7
h   1   4
i   1   1

Résultat

Ce qui suit est la fin de ce qui est imprimé dans la console lorsque j'exécute mon code, et inclut la partie que je n'arrive pas à comprendre :

25: i
Has next line: true
Has next: true
26: 1
Has next line: true
Has next: true
27: 1
Has next line: true
Has next: false

24 votes

Y a-t-il par hasard une ligne vide à la fin de votre fichier d'entrée ?

15 votes

hasNextLine() retourne vrai s'il y a une ligne suivante, même vide. hasNext() retourne vrai s'il y a un jeton de plus. Une ligne vide est une ligne qui ne contient pas de jeton.

1 votes

Je pense next ne consomme pas le \n Le "curseur" se trouve donc juste avant le saut de ligne, il y a donc une ligne suivante, mais il n'y a plus de jeton.

59voto

durron597 Points 9165

Vous avez un seul saut de ligne supplémentaire à la fin de votre fichier.

Puisque le délimiteur de l'analyseur est l'espace blanc, et que l'option linePattern est également un espace blanc, il est possible qu'il y ait une linePattern dans le tampon mais pas d'expressions analysables.

En général, la façon la plus courante de traiter ce problème est de toujours appeler nextLine() après avoir analysé tous les tokens (par exemple, les nombres) dans chaque ligne de votre texte. Vous devez effectuer cette opération lorsque vous utilisez Scanner lors de la lecture de l'entrée d'un utilisateur également à partir de System.in . Pour faire avancer le scanner au-delà de ce délimiteur d'espace blanc, vous devez utiliser scanner.nextLine() pour effacer le délimiteur de ligne. Voir : Utilisation de scanner.nextLine()


Annexe :

LinePattern est défini comme étant un Pattern qui correspond à ça :

private static final String LINE_SEPARATOR_PATTERN =
                                       "\r\n|[\n\r\u2028\u2029\u0085]";
private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$";

Le délimiteur de jeton par défaut est le suivant Pattern :

private static Pattern WHITESPACE_PATTERN = Pattern.compile(
                                            "\\p{javaWhitespace}+");

0 votes

Tout d'abord, merci pour la réponse détaillée. Je comprends donc qu'il peut y avoir un Line_Separator_Pattern sans qu'un autre jeton soit présent. Cependant, dans le fichier, je ne peux pas faire avancer mon curseur au-delà du "1" final. Y a-t-il un caractère d'espacement que je ne peux pas supprimer avec gedit ?

0 votes

"You have a single extra newline at the end of your file." - Je pense que c'est plus général que cela, comme dans - il y a n'importe quelle quantité d'espace blanc (ou n'importe quel délimiteur que vous avez spécifié) à la fin du fichier.

0 votes

@Dukeling oui, mais OP a déclaré quelque part qu'il a vérifié son fichier et qu'il n'y avait pas d'espace blanc supplémentaire.

16voto

Daniel Centore Points 317

La raison en est que hasNext() vérifie s'il y a encore des caractères non blancs disponibles. hasNextLine() vérifie s'il y a une autre ligne de texte disponible. Votre fichier texte a probablement un saut de ligne à la fin, de sorte qu'il y a une autre ligne mais plus de caractères qui ne sont pas des espaces.

De nombreux éditeurs de texte ajoutent automatiquement une nouvelle ligne à la fin d'un fichier s'il n'y en a pas déjà une.

En d'autres termes, votre fichier d'entrée n'est pas celui-ci (les numéros sont des numéros de ligne) :

1. a   3   9
2. b   3   6
3. c   3   3
4. d   2   8
5. e   2   5

C'est en fait ça :

1. a   3   9
2. b   3   6
3. c   3   3
4. d   2   8
5. e   2   5
6.

14voto

kamwo Points 124

Réponse courte

Vous avez une ligne vide à la fin du fichier.


Raison de la ligne vide

Si vous prenez votre contenu et l'enregistrez par exemple dans un fichier txt, certains éditeurs ajouteront une nouvelle ligne vide à votre fichier.

Les rédacteurs se comportent de cette manière, car cela fait partie de la stratégie de l POSIX standard :

3.206 Ligne

Une séquence de zéro ou plus de non caractères plus un caractère de terminaison.

Ce sujet a été abordé dans ce fil .


Documentation sur le scanner Java

Voici la documentation du Classe Java 8 Scanner .

hasNext()

Retourne true si cet analyseur a un autre token dans son entrée.


hasNextLine()

Renvoie vrai s'il y a une autre ligne dans l'entrée de cet analyseur.


Raison du comportement du code Java

En raison des faits décrits ci-dessus, hasNextLine() retournera true mais hasNext() ne peut rien trouver qu'il puisse reconnaître comme Token et renvoie donc false .

Pour plus d'informations, voir durron597 poste.

5voto

Florian Schaetz Points 3166

Vous consommez la valeur de next() mais en demandant hasNext() y hasNextLine() . next() par défaut, renvoie tout au prochain whitespace() . Ainsi, vous itérez à travers toutes les chaînes de caractères séparées par des espaces, et après chacune d'entre elles, vous posez la question de l'élément nextLine() .

i 1 1 -> hasNextLine() ? C'est vrai. hasNext() ? C'est vrai aussi.

1 1 -> hasNextLine() ? C'est vrai. hasNext() ? Egalement vrai (il reste encore un espace)

1 -> hasNextLine() ? Vrai (Séparateur de ligne, probablement). haxNext ? Faux, plus d'espaces blancs.

0voto

Le concept de base de hasNext() et hasNextLine() est le suivant

hasNextLine :- Renvoie vrai s'il y a une autre ligne dans l'entrée de cet analyseur. Cette méthode peut se bloquer pendant l'attente des données. Le scanner n'avance pas en cas de saisie.

Les retours : vrai si et seulement si cet analyseur a une autre ligne d'entrée Lance : IllegalStateException - si l'analyseur est fermé.

hasNext

Retourne vrai si le prochain token complet correspond au motif spécifié.

Un jeton complet est préfixé et postfixé par l'entrée qui correspond au motif du délimiteur. Cette méthode peut se bloquer en attendant l'entrée. L'analyseur n'avance pas au-delà d'une entrée.

Paramètres : motif - le motif à rechercher

Les retours : vrai si et seulement si cet analyseur a un autre jeton correspondant au modèle spécifié

Puisque votre dernière entrée dit vrai pour nextLine() parce qu'un appel à scan.nextLine() ; retourne le jeton suivant. Il est important de noter que l'analyseur renvoie un espace et une lettre, car il lit depuis la fin du dernier jeton jusqu'au début de la ligne suivante.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X