我使用下面的代码在命令行上从stdin读取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();
}
我的问题是应用程序有时需要运行来自stdin的数据,有时不需要(没有管道输入)。如果上述代码中没有输入,则in.readLine()
会阻止。有没有办法重写这段代码,以便在没有管道输入的情况下它仍可以运行?
更新:该应用程序旨在从命令行而不是键盘中获取管道数据。
答案 0 :(得分:2)
您可以使用ready
来测试流是否已准备好数据。如果ready
返回false
,则在您调用它时,流没有准备好数据(它可能在稍后的一微秒内收到数据)。如果您致电ready
并返回true
,则表示您可以在不阻止的情况下致电read
。 (当然,你可能无法在没有阻止的情况下拨打readLine
。)
答案 1 :(得分:2)
我认为没有办法检查你是否最终会得到另一行输入。请注意,如果用户关闭输入流(例如,在终端中使用^ D),则当前代码会终止。
BufferedReader.ready()
检查流上是否有一些数据。像T.J.提到,你可能不幸并且在你实际收到数据之前就要求数据,而你的用户会因为你没有回答他们的问题而感到难过。
Scanner.hasNextLine()
是一个阻止操作,所以可能不是你想要的。
您可以让用户指定是否从System.in读取,例如使用命令行参数。
答案 2 :(得分:1)
支持从stdin可选读取的Unix实用程序通常会根据命令行确定要执行的操作。例如,如果命令行中没有命名文件,cat
将从stdin读取。您可以沿着这些方向执行某些操作 - 添加命令行标志或选项或其他内容以指示程序是否应尝试从stdin读取任何内容。
另一种方法是,如果没有您希望程序读取的输入,则从/ dev / null重定向输入。在这种情况下,您可以从stdin读取并立即获得文件结束指示。等效的窗口是从NUL
重定向。
如果你真的需要你的程序来检测它是否可以在没有阻塞的情况下从stdin中读取,请查看InputStream.available()
。但是如果你想支持某人输入程序的输入(或者将其复制粘贴到终端窗口中,比如说),那么在用户实际输入内容之前,InputStream不会显示输入。
答案 3 :(得分:0)
这取决于没有管道输入时程序的运行方式。通常一个程序将有一个打开的标准输入,你所能做的只是设置一个计时器,等待一定的时间进行输入,如果计时器没有输入到期,假设没有任何输入。替代方案是安排程序在stdin关闭的情况下运行,在这种情况下,当您尝试阅读时,您将获得EOF。
要在unix(包括Mac OS)中关闭stdin,你需要编写一个bash脚本来启动你的程序:
#!/bin/bash
exec 0>&- # close stdin
java -jar yourProgram.jar # run your program
当然,如果您从bash命令行启动,则不需要脚本:
prompt> java -jar yourProgram.jar 0>&-
但是如果你的程序是在Java EE容器中运行的,我不知道你在启动之前如何关闭stdin,也许你不能。
答案 4 :(得分: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]
这将告诉您输入是文件,管道输入还是终端。