我正在做一个需要接收和处理控制台输入的项目。我使用eclipse并意外发现,当我在控制台中按CTRL+Z时(之后没有按ENTER),程序崩溃并出现NoSuchElementException,我认为这是由Scanner.nextLine()
方法抛出的。下面是它的简化版本。
Test.java
import java.util.NoSuchElementException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = "";
while(true) {
System.out.printf("Say something: ");
input = scanner.nextLine();
String output = input.trim().toUpperCase();
if(output.equals("Q")) {
break;
}
System.out.printf("Uppercase: %sn", output);
}
scanner.close();
}
}
这是我的测试运行:
Say something: hey
Uppercase: HEY
Say something: i'm boutta crash this program by pressing ctrl+z
Uppercase: I'M BOUTTA CRASH THIS PROGRAM BY PRESSING CTRL+Z
Say something: Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1656)
at Test.main(Test.java:11)
我还用javac Test.java
编译了.java文件,并在Windows命令提示符中使用java Test
运行。下面是输出:
C:>cd Test
C:Test>javac Test.java
C:Test>java Test
Say something: i'm gonna press ctrl+c
Uppercase: I'M GONNA PRESS CTRL+C
Say something: Exception in thread "main" java.util.NoSuchElementException: No line found
^C
C:Test>
是否有任何方法可以防止CTRL+Z和CTRL+V被扫描仪读取?提前感谢您的帮助/解释。
我试着用try/catch块包围input = scanner.nextLine();
行。这是我的尝试。
try {
input = scanner.nextLine();
} catch(NoSuchElementException e) {
scanner = new Scanner(System.in);
System.out.printf("caught NoSuchElementExceptionn");
}
我得到了一个无限循环。
Say something: pressing ctrl+z...
Uppercase: PRESSING CTRL+Z...
Say something: caught NoSuchElementException
Uppercase: PRESSING CTRL+Z...
Say something: caught NoSuchElementException
Uppercase: PRESSING CTRL+Z...
Say something: caught NoSuchElementException
Uppercase: PRESSING CTRL+Z...
...
windows中的ctrl+z或Linux中的ctrl-d是用于结束输入的DOS命令。因此,如果您在Linux中部署您的程序,对于ctrl-d的输入,它的行为将是相同的。您应该通过调用方法scanner.hasNextLine()
来处理此问题,该方法仅在有输入时返回true。我附上了修改后的程序,可以运行。
public class ControlPlusZ {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = "";
while(true) {
System.out.printf("Say something: ");
if(scanner.hasNextLine()) {
System.out.println(scanner.hasNextLine());
input = scanner.nextLine();
String output = input.trim().toUpperCase();
if(output.equals("Q")) {
break;
}
System.out.printf("Uppercase: %sn", output);
}
else {System.out.println("Closing scanner");
break;}}
scanner.close();
}
}
我在寻找一个像@Rajnish的答案,经过一些修补测试它是如何工作的,我有一个解决方案:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = "";
while (true) {
System.out.print("Say something: ");
// THIS IS MY SOLUTION
if (!scanner.hasNextLine()) {
break;
}
input = scanner.nextLine();
String output = input.trim().toUpperCase();
if (output.equals("Q")) {
break;
}
System.out.printf("Uppercase: %sn", output);
}
scanner.close();
}
}
基本上,这告诉扫描器我们希望输入是一个以换行符分隔的字符串,但我们实际上还没有接受输入(从Java文档中,扫描器不会向前推进超过任何输入)。如果用户确实输入了一个字符串,那么input = scanner.nextLine();
将接收该输入。但是,如果用户输入不同的内容(例如Ctrl+C),则!scanner.hasNextLine()
将为真,从而使用户脱离循环。