无法将值从Bash脚本传递到Java程序

时间:2014-02-26 05:07:41

标签: java linux bash shell

我正在尝试从bash脚本执行java程序。我将脚本中的输入值提供给程序。

Java代码。

import java.util.Scanner;
import java.io.*;

public class test{
public static void main(String[] args) {
int a = 0;
String str = "";
String str2 = " ";
System.out.println("hello");
Scanner sc = new Scanner(System.in);

//System.out.println(a);

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
str = br.readLine();
str2 = br.readLine();
System.out.println(str + str2);

} catch(IOException ex) {
 System.out.println("exception: " + ex);
}

 for (int i = 0; i < 2; i++) {
  a = sc.nextInt();
 }

 }
}

bash脚本run.sh

#!/bin/sh

java test <<EOF
abc
def
5
6
EOF

但运行脚本./run.sh的输出如下:

hello
abcdef
Exception in thread "main" java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Scanner.java:907)
    at java.util.Scanner.next(Scanner.java:1530)
    at java.util.Scanner.nextInt(Scanner.java:2160)
    at java.util.Scanner.nextInt(Scanner.java:2119)
    at test.main(test.java:25)

任何人都可以帮助我。

3 个答案:

答案 0 :(得分:0)

Scanner sc = new Scanner(System.in);

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

您不能将扫描仪和阅读器连接到同一个流上。他们会窃取对方的意见。

对于您的输入,可以安全地更改

a = sc.nextInt();

a = Integer.parseInt(br.readLine());

答案 1 :(得分:0)

你正在使用两个不同的读者同时尝试处理System.in流,这将保证不可预测和不正确的结果 - 想象一下,如果两个不同的人试图捕获河里的所有鱼;至少有一个人不会这样做。在这种特殊情况下,问题可能源于使用BufferedReader,其读取的内容超出了您的要求,以便更快地响应来自流的未来请求。

然而,关键是选择一种方法来读取输入并坚持使用它。在您的情况下,我建议坚持Scanner并保留Reader行为。请考虑以下事项:

try(Scanner sc = new Scanner(System.in)) {
  str = sc.next();
  str2 = br.next();
  System.out.println(str + str2);

  for (int i = 0; i < 2; i++) {
    a = sc.nextInt();
  }
} catch(IOException ex) {
  System.out.println("exception: " + ex);
}

请注意以下几点:

  1. 我们使用try-with-resources确保Scanner在完成后关闭流
  2. 我们将所有流读取行为包装在try块中,因为它可能会失败的任何部分
  3. 我们使用Scanner.next()从输入中读取单词,避免需要Reader
  4. 还要注意Scanner的{​​{1}}方法,这些方法可用于验证流中的下一个项目是否存在,并且是您期望的类型。如果传入的内容完全符合您描述的格式,那么您当前的代码仍然会剧烈失败。使用has*()方法时,如果传入意外输入,您可以更优雅地出错。


    要明确的是,这既不是has*()也不是bash的问题 - 它们的行为完全符合记录。它在browxy.com上成功运行(无论是什么)仅仅是巧合,事实上表明他们对java的实现非常糟糕。

答案 2 :(得分:0)

为什么不将main的方法签名更改为main(String... args)并通过命令行传递它们呢?

java test abc def 5 6

快速举例:

public class Test {

  public static void main(String... args) {

    for (String s : args) {
      System.out.println("String is: " + s);
    }
  }

}