如何用bash管道输入到Java程序



我的Java程序正在监听标准输入:

InputStreamReader isReader = new InputStreamReader(System.in);
BufferedReader bufReader = new BufferedReader(isReader);
while(true){
    try {
        String inputStr = null;
        if((inputStr=bufReader.readLine()) != null) {
            ...
        }
        else {
            System.out.println("inputStr is null");
        }
    }
    catch (Exception e) {
        ...
    }
}

现在,我想从bash管道输入到这个程序。我尝试了以下操作:

echo "hi" | java -classpath ../src test.TestProgram

但是它只是无限次地打印inputStr is null。我做错了什么?

编辑1:更新问题以包含更多代码/上下文。


编辑2:

看起来我遇到了与此OP相同的问题:Java中的命令行管道输入

我如何修复程序,以便我可以管道输入用于测试,但正常运行程序将允许用户在标准输入上输入?

你有while(true),所以你会得到无限循环

在循环中添加break是修复它的一种方法。但这不是一个好的风格,因为读者必须在循环中寻找它是否退出以及何时退出。

最好让您的while语句清楚地显示退出条件是什么:

String inputStr = "";
while(inputStr != null) {
    inputStr=bufReader.readLine(); 
    if(inputStr != null) {
        ...
    } else {
        System.out.println("inputStr is null");
    }
}

修复。输入的管道完成后,readLine()继续返回null,因此无限循环继续循环。

解决方法是在readLine()返回null时跳出无限循环。

我喜欢slim的回答,只是我的处理方式有点不同。这是我用来逐行读取文本流的基本模板。

try {
    // Wrap the System.in inside BufferedReader
    // But do not close it in a finally block, as we 
    // did no open System.in; enforcing the rule that
    // he who opens it, closes it; leave the closing to the OS.
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    String line;
    while ((line = in.readLine()) != null) {
        // TODO: Handle input line
    }
    // Null was received, so loop was aborted.
} catch (IOException e) {
    // TODO: Add error handler
}

如果我正在读取一个文件,我会稍微改变一下,像这样关闭文件

try {
    File file = new File("some_file.txt");
    // Wrap the System.in inside BufferedReader
    // But do not close it in a finally block, as we
    // did no open System.in; enforcing the rule that
    // he who opens it, closes it; leaves the closing to the OS.
    BufferedReader in = new BufferedReader(new FileReader(file));
    try {
        String line;
        while ((line = in.readLine()) != null) {
            // TODO: Handle input line
        }
        // Null was received, so loop was aborted.
    } finally {
        try {
            in.close();
        } catch (IOException e) {
        }
    }
} catch (IOException e) {
    // TODO: Add error handler
}

我做错了什么?

我看不出这段代码为什么会这样。我怀疑问题出在你没有展示给我们的东西上。

例如,您使用的是哪个版本的echo ?造壳?"/bin"中的标准版本?某个古怪的家伙在你的搜索路径上?

您可以尝试一些简单的实验来确定问题是在shell/命令级别还是在Java应用程序中;例如

$ echo hi > tmp
$ cat tmp
$ java -classpath ../src test.TestProgram < tmp
$ cat tmp | java -classpath ../src test.TestProgram

等等。

如果这些实验都没有提供任何线索,那么就发布一个小程序的真实Java源代码来演示您的问题。

(正如@trashgod正确指出的那样,您可能"肥手指"了构建步骤,并且运行的程序版本不再与您的源代码匹配。)

您可以考虑使用命名管道(fifo)来允许通过控制终端/dev/tty(或/dev/stdin)的正常输入和通过输入fifo的管道输入。

参见:重定向应用程序(java)的输入,但仍然允许BASH中的stdin

相关内容

  • 没有找到相关文章

最新更新