返回

如何避免 Java.util.Scanner 在后台运行时抛出 NoSuchElementException 异常?

Linux

使用 Java.util.Scanner 在后台运行时避免 NoSuchElementException

引言

Java 程序通常使用 java.util.Scanner 类从标准输入中读取数据。然而,当 Java 程序在后台运行时,使用 & 标记,可能会遇到 java.util.NoSuchElementException 异常。本文将深入探讨这个问题的原因,并提供两种可行的解决方案。

问题:背景运行时停止响应

当 Java 程序在后台运行时,标准输入会关闭,导致 Scanner 无法读取任何数据。这会导致以下问题:

  • 使用 nohup java -jar my.jar & 时,程序会抛出 java.util.NoSuchElementException 异常,表明程序正在后台运行。
  • 使用 java -jar my.jar & 时,程序会停止运行,并在终端输出 [1]+ 已停止

解决方案

解决方案 1:使用 ProcessBuilder

ProcessBuilder 可以创建一个新进程,并指定其标准输入、标准输出和标准错误流。通过将标准输入重定向到一个管道,我们可以避免 Scanner 在后台运行时遇到问题:

ProcessBuilder pb = new ProcessBuilder("java", "-jar", "my.jar");
pb.redirectInput(ProcessBuilder.Redirect.PIPE);
Process process = pb.start();
process.getOutputStream().write("Hello, world!".getBytes());
Scanner scanner = new Scanner(process.getInputStream());
while (scanner.hasNextLine()) {
    System.out.println(scanner.nextLine());
}
process.waitFor();

解决方案 2:使用 System.in.available()

System.in.available() 方法可以检查标准输入流中是否有可用的字节。如果流中没有可用字节,则表示标准输入已关闭,程序正在后台运行。我们可以使用以下代码来检测此情况:

while (System.in.available() > 0) {
    String s = scanner.nextLine();
    System.out.println("s = " + s);
}
System.out.println("I'm running in the background!");

结论

通过使用 ProcessBuilderSystem.in.available(),我们可以解决 java.util.Scanner 在后台运行时遇到的问题,并确保程序正常读取输入数据。

常见问题解答

  1. 为什么在后台运行时会出现这个问题?
    因为标准输入在后台运行时关闭了。

  2. 这两个解决方案有什么区别?
    ProcessBuilder 创建一个新进程,并允许我们控制标准输入,而 System.in.available() 允许我们检查标准输入流是否关闭。

  3. 哪个解决方案更好?
    取决于具体情况,ProcessBuilder 更通用,而 System.in.available() 更简单。

  4. 是否还有其他解决方案?
    还有一些其他解决方案,如使用管道或死信管道,但它们更复杂。

  5. 如何判断程序是否正在后台运行?
    可以使用 ProcessBuilder.isRunning() 方法或 System.in.available() 方法来检查。