有没有办法有时需要来自stdin的数据,有时候不需要Java?

时间:2012-04-25 16:25:42

标签: java pipe stdin

我使用下面的代码在命令行上从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()会阻止。有没有办法重写这段代码,以便在没有管道输入的情况下它仍可以运行?

更新:该应用程序旨在从命令行而不是键盘中获取管道数据。

5 个答案:

答案 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]

这将告诉您输入是文件,管道输入还是终端。