如何使用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无限次inputStr is null 。 我究竟做错了什么?

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


编辑2:

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

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

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

readLine()返回null时,修复是从无限循环中断开。

你有while(true) ,所以无限循环是你将得到的。

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

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

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

我究竟做错了什么?

我认为没有理由说明代码片段的行为方式。 我怀疑问题出在你没有告诉我们的事情上……

例如,您使用的是哪个版本的echo ? 壳内置? ‘/ bin’中的标准版本? 你搜索路径上有些时髦吗?

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

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

等等。

如果这些实验都没有产生任何线索,请发布一个演示您问题的小程序的真实Java源代码。

(正如@trashgod正确地指出的那样,你可能会有“胖手指”构建步骤,并且正在运行一个不再与源代码匹配的程序版本。)

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

请参阅: 重定向应用程序的输入(java),但仍允许在BASH中使用stdin

我喜欢苗条的答案,只是我倾向于处理它有点不同。 这是我用来逐行读取文本流的基本模板。

 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 }