0

我正在使用下面的代码在命令行上从标准输入读取 sql 语句:

    BufferedReader in = null;
    StringBuilder sb = new StringBuilder();
    String line = null;
    try {
        in = new BufferedReader(new InputStreamReader(System.in));
        while((line = in.readLine()) != null) {
            sb.append(line);
        }
    } finally {
        if (in!=null) in.close();
    }

我的问题是应用程序有时需要使用来自标准输入的数据运行,有时不需要(无管道输入)。如果上述代码中没有输入,则in.readLine()阻塞。有没有办法重写这段代码,以便在没有任何管道输入的情况下它仍然可以运行?

更新:该应用程序旨在期望来自命令行的管道数据,而不是来自键盘的数据。

4

5 回答 5

2

您可以使用ready来测试流是否已准备好数据。如果ready返回false,则当您调用它时,该流没有准备好数据(它可能在一微秒后接收到数据)。如果您调用ready并且它返回true,则您知道您可以read在没有阻塞的情况下调用。(当然,您可能无法在readLine没有阻塞的情况下拨打电话。)

于 2012-04-25T16:29:44.320 回答
2

我认为没有任何方法可以检查您是否最终会获得另一行输入。请注意,如果用户关闭输入流(例如,在终端中使用 ^D),您当前的代码会终止。

BufferedReader.ready()检查流上是否有一些数据。就像 TJ 提到的那样,您可能不走运并在实际收到数据之前就要求提供数据,您的用户会因为您没有回答他们的查询而感到难过。

Scanner.hasNextLine()是一个阻塞操作,所以可能不是你要找的。

您可以让用户指定是否从 System.in 读取,例如通过使用命令行参数。

于 2012-04-25T16:43:47.963 回答
1

支持选择性地从标准输入读取的 Unix 实用程序通常会根据它们的命令行确定要做什么。例如,cat如果命令行上没有命名文件,将从标准输入读取。您可以按照这些方式做一些事情——添加一个命令行标志或选项或其他东西来指示程序是否应该尝试从标准输入读取任何内容。

如果没有您希望程序读取的输入,另一种方法是从 /dev/null 重定向输入。在这种情况下,您可以从标准输入读取并立即获得文件结束指示。windows 等价于从NUL.

如果您确实需要您的程序来检测它是否可以从标准输入读取而不阻塞,请查看InputStream.available(). 但是,如果您想支持某人在程序的输入中键入(或将其复制粘贴到终端窗口中),那么在用户实际键入内容之前,InputStream 不会将输入显示为可用。

于 2012-04-25T17:02:24.807 回答
0

这取决于没有管道输入时程序的运行方式。一般来说,一个程序会有一个开放的标准输入,你所能做的就是设置一个计时器,等待一段时间的输入,如果计时器在没有输入的情况下到期,假设不会有任何输入。另一种方法是安排程序在标准输入关闭的情况下运行,在这种情况下,当您尝试阅读时会得到一个 EOF。

要在 unix(包括 Mac OS)中关闭标准输入,您需要编写一个 bash 脚本来启动您的程序:

#!/bin/bash

exec 0>&- # close stdin

java -jar yourProgram.jar # run your program

当然,如果您还是从 bash 命令行启动,则不需要脚本:

prompt> java -jar yourProgram.jar 0>&-

但是,如果您的程序在 Java EE 容器中运行,我不知道您将如何在启动前关闭标准输入,也许您不能。

于 2012-04-25T17:06:16.753 回答
0

在 unix 上,您可以检查是否/proc/self/fd/0指向文件、管道或来自控制台。

$ ls -l /proc/self/fd/0
lrwx------ 1 peter peter 64 Apr 25 18:12 /proc/self/fd/0 -> /dev/pts/21
$ ls -l /proc/self/fd/0 < /dev/null
lr-x------ 1 peter peter 64 Apr 25 18:13 /proc/self/fd/0 -> /dev/null
$ echo Hello World | ls -l /proc/self/fd/0 
lr-x------ 1 peter peter 64 Apr 25 18:13 /proc/self/fd/0 -> pipe:[139250355]

这将告诉您输入是文件、已通过管道传输还是终端。

于 2012-04-25T17:16:15.953 回答