java.util.Scanner与CTRL+Z, CTRL+C, CTRL+X的问题



我正在做一个需要接收和处理控制台输入的项目。我使用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()将为真,从而使用户脱离循环。

最新更新