Scanner调用next方法时报错NoSuchElementException原因,及对Scanner的一些总结

  1. 对象new Scanner(System.in)调用close()后,如果又使用重新创建了对象,在调用next方法时报错NoSuchElementException

    jshell> Scanner s = new Scanner(System.in);
    s ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
    
    jshell> s.next();
    Hello
    $2 ==> "Hello"
    
    jshell> s.close();
    
    jshell> Scanner s1 = new Scanner(System.in);
    s1 ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
    
    jshell> s1.next();
    |  异常错误 java.util.NoSuchElementException
    |        at Scanner.throwFor (Scanner.java:937)
    |        at Scanner.next (Scanner.java:1478)
    |        at (#5:1)
    
    jshell> Scanner s2 = new Scanner("Hello world\n");
    s2 ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
    
    jshell> s2.next();
    $7 ==> "Hello"
    
    jshell> s2.close();
    
    jshell> Scanner s3 = new Scanner("world\n");
    s3 ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
    
    jshell> s3.next();
    $10 ==> "world"
    

    可见,上述Scanner的实例中只有构造方法传入System.in的不能再重新创建。
    原因:
    在调用s1.close()方法时,系统关闭了System.in,而且不能再重新打开。
    解决方案:
    使用完后不调用close方法。
    参考:https://www.cnblogs.com/Sunrises/p/7277162.html

  2. 使用next方法读取时会跳过分隔符(默认为空白符包括空格,\t,\n, \r等),分割符可通过useDelimiter指定:

     Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
    
  3. nextLine

    3.1 该方法会取走该行剩余部分,并返回行分隔符之前的部分

    jshell>  String input = "1 fish 2 fish red fish blue fish";
       ...>  Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
    input ==> "1 fish 2 fish red fish blue fish"
    s ==> java.util.Scanner[delimiters=\s*fish\s*][position ... \E][infinity string=\Q∞\E]
    
    jshell> s.next()
    $3 ==> "1"
    
    jshell> s.nextLine()
    $4 ==> " fish 2 fish red fish blue fish"
    
    jshell> s.hasNext()
    $5 ==> false
    

    3.2 如果当前行只剩行分隔符,则返回空字符串""

    3.2.1 使用 \n作行分割符:

     jshell> Scanner sc = new Scanner("\n");
     sc ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
     
     jshell> sc.nextLine();
     $7 ==> ""
    

    3.2.2 使用\r\n作行分隔符:

    jshell> Scanner sc = new Scanner("\r\n");
    sc ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
    
    jshell> sc.nextLine();
    $9 ==> ""
    

    比较全的例子:

    jshell> Scanner s2 = new Scanner("2020\nThe meaning\rof\tlife\nis\r\nto\nfind\r\nyour gift");
    s2 ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
    
    jshell> s2.nextInt();
    $45 ==> 2020
    
    jshell> s2.next();  //遇到空格
    $46 ==> "The"
    
    jshell> s2.next();  //遇到回车符\r
    $47 ==> "meaning"
    
    jshell> s2.next();  //遇到制表符\t
    $48 ==> "of"
    
    jshell> s2.next();  //遇到换行符\n
    $49 ==> "life"
    
    jshell> s2.next();  //遇到回车换行
    $50 ==> "is"
    
    jshell> s2.nextLine();  //从缓冲区取走回车换行
    $51 ==> ""
    
    jshell> s2.nextLine();
    $52 ==> "to"
    
    jshell> s2.nextLine();
    $53 ==> "find"
    
    jshell> s2.nextLine();  
    $54 ==> "your gift"
    
    jshell> s2.nextLine();  //缓冲区无内容
    |  异常错误 java.util.NoSuchElementException:No line found
    |        at Scanner.nextLine (Scanner.java:1651)
    |        at (#55:1)
    

你可能感兴趣的:(JAVA)