web-dev-qa-db-ja.com

hasNext()はFalseですが、hasNextLine()はTrueなのはなぜですか?

質問

スキャナオブジェクトのhasNextLine()メソッドがtrueを返し、hasNext()メソッドがfalseを返すのはどうですか?

注:入力ファイルに基づいて、hasNext()メソッドは期待どおりの結果を返します。 hasNextLine()は正しい結果を返さないようです。

コード

以下は、私が実行しているコードで、以下の結果を作成しています。

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

入力ファイル

以下は、このスキャナーに渡すファイルの実際の内容です。

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

結果

以下は、コードを実行したときにコンソールに出力される内容の最後であり、意味をなさない部分も含まれています。

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
61
DRich

ファイルの最後に1つの余分な改行があります。

  • hasNextLine() バッファに別のlinePatternがあるかどうかを確認します。
  • hasNext() は、スキャナーの区切り文字で区切られた、解析可能なトークンがバッファーにあるかどうかを確認します。

スキャナーの区切り文字は空白であり、linePatternも空白であるため、バッファーにlinePatternが存在する可能性がありますが、解析可能なトークンは存在しません。

通常、この問題に対処する最も一般的な方法は、テキストの各行のすべてのトークン(数値など)を解析した後、常にnextLine()を呼び出すことです。 _System.in_からユーザーの入力も読み取るときにScannerを使用する場合は、これを行う必要があります。この空白区切り文字を超えてスキャナを進めるには、scanner.nextLine()を使用して行区切り文字をクリアする必要があります。参照: scanner.nextLine()の使用


付録:

LinePatternは、これに一致する Pattern として定義されます。

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

デフォルトのトークン区切り文字は次のPatternです。

_private static Pattern WHITESPACE_PATTERN = Pattern.compile(
                                            "\\p{javaWhitespace}+");
_
58
durron597

その理由は、hasNext()が使用可能な非空白文字がさらにあるかどうかをチェックするからです。 hasNextLine()は、使用可能なテキストの別の行があるかどうかを確認します。テキストファイルの末尾にはおそらく改行があるため、別の行がありますが、空白ではない文字はありません。

多くのテキストエディターは、ファイルの最後に改行がまだない場合、自動的に改行を追加します。

つまり、入力ファイルはこれではありません(数字は行番号です)。

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

実際にはこれです:

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

短い答え

ファイルの最後に空の行があります。


空行の理由

コンテンツを取得して、たとえばtxtファイルに保存すると、一部のエディターはファイルに空の新しい行を追加します。

これは [〜#〜] posix [〜#〜] 標準の一部であるため、エディターはこのように動作します。

3.206 Line

ゼロ個以上の非文字と終了文字のシーケンス。

このトピックは this thread で説明されています。


Javaスキャナーのドキュメント

Java 8 Scannerクラス のドキュメントを次に示します。

hasNext()

このスキャナーの入力に別のトークンがある場合、trueを返します。


hasNextLine()

このスキャナーの入力に別の行がある場合、trueを返します。


Javaコードの動作の理由

上記の事実により、hasNextLine()trueを返しますが、hasNext()は何も検出できず、Tokenとして認識できるため、false

詳細については、 durron597 postを参照してください。

14
kamwo

next()の値を使用していますが、hasNext()およびhasNextLine()を要求しています。 next()は、デフォルトで、すべてを次のwhitespace()に返します。したがって、空白で区切られたすべての文字列を繰り返し処理し、それぞれの後にnextLine()について質問しています。

_i 1 1_-> hasNextLine()?本当です。 hasNext()?本当です。

_1 1_-> hasNextLine()?本当です。 hasNext()?真(まだ空白が残っている)

_1_-> hasNextLine()? True(行セパレーター、おそらく)。 haxNext? False、空白はもうありません。

5
Florian Schaetz

HasNext()およびhasNextLine()の基本概念は

hasNextLine:-このスキャナーの入力に別の行がある場合にtrueを返します。このメソッドは、入力を待機している間ブロックする場合があります。スキャナーは入力を通過しません。

戻り値: trueこのスキャナーが別の入力行を持っている場合にのみスロー:IllegalStateException-このスキャナーが閉じられている場合

hasNext

次の完全なトークンが指定されたパターンに一致する場合、trueを返します。

完全なトークンには、区切り文字パターンに一致する入力がプレフィックスとポストフィックスとして付加されます。このメソッドは、入力の待機中にブロックする場合があります。スキャナーは入力を通過しません。

パラメータ: pattern-スキャンするパターン

戻り値:このスキャナーが指定されたパターンに一致する別のトークンを持っている場合にのみtrue

Scan.nextLine()の呼び出しにより、nextLine()に対して最後の入力がtrueとなるため。次のトークンを返します。 スキャナはスペースと文字を返します。これは、最後のトークンの末尾から次の行の先頭まで読み取るためです。

0
Manpreet gujral