将程序输出重定向为输入 - 管道不工作

Redirecting program output as input - pipe not working

我使用 BufferedReader 将一个程序 (C++) 的输出作为另一个程序 (Java) 的输入。当我 运行 我的 IDE 中的 Java 程序并在控制台中输入输入时,该程序按预期工作,但是,当我尝试通过管道从 C++ 程序输入时,它不再工作没有给出错误 - 终端 window 上没有显示输出,也没有数据输入数据库。还值得注意的是,如果我尝试 运行 在终端 window 中输入 jar 并输入输入,程序也不会在那里工作。

Reader代码:

BufferedReader input;
      try {
        input = new BufferedReader(new InputStreamReader(System.in));
        String outputLine;
        String visionObjectName;
        String visionObjectTimestamp;
        String word = null;
        String timestamp = null;
        String whiteSpace = null;
        // Regex is used to check that the output is an object "name blankSpace timestamp" to avoid random output such as errors being entered.
        while ((outputLine = input.readLine()) != null) {
          System.out.println(outputLine);
          String regEx = "(^[a-zA-Z]*)(\s+)((?:2|1)\d{3}(?:-|\/)(?:(?:0[1-9])|(?:1[0-2]))(?:-|\/)(?:(?:0[1-9])|(?:[1-2][0-9])|(?:3[0-1]))(?:T|\s)(?:(?:[0-1][0-9])|(?:2[0-3])):(?:[0-5][0-9]):(?:[0-5][0-9]))";
          Pattern p = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
          Matcher m = p.matcher(outputLine);
          if (m.find()) {
            word = m.group(1);
            whiteSpace = m.group(2);
            timestamp = m.group(3);
          }
          visionObjectName = word + "" + whiteSpace;
          visionObjectTimestamp = timestamp;
          databasePopulation(visionObjectName, visionObjectTimestamp);
        }

我正在使用 Linux 终端管道功能来传递信息。

命令:

./ORBMarkerDetection | java -jar ../layers/out/artifacts/layers_jar/layers.jar

编辑: 为了彻底起见,我包含了 C++ 程序的输出代码,我用来打印时间戳的方法会导致问题吗?

int timeFound() {
  time_t rawtime;
  struct tm * timeinfo;
  char buffer [80];
  time(&rawtime);
  timeinfo = localtime (&rawtime);
  strftime(buffer,80,"%Y-%m-%d %H:%M:%S",timeinfo);
  puts(buffer);
  return 0;
}

void printFunction(String objectName) {
  if(nameArray[0] != objectName) {
    nameArray[0] = objectName;
    cout << nameArray[0] << " ";
    timeFound();
    cout << flush;
  }
}

如评论中所述,这是 C++ 输出的示例(从行 Aug 17....opengl support available 仅在程序启动时打印,不会再次打印。

Aug 17, 2015 11:57:03 AM com.layers.Main main
INFO: Logger Created.
Please enter activity number: 
1.1
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
init done 
opengl support available 
tap 2015-08-17 11:57:07
kitchenDoor 2015-08-17 12:57:07
fridge 2015-08-17 13:57:07

此外,如果我注释掉从开始到结束的行:

String regEx...
...
}

Java 程序按预期输出到终端,但我不得不注释掉数据库上传以测试它,所以我无法验证上传是否有效。

我的猜测是您的程序被与管道无关的东西阻塞了。最有可能是数据库。 IDE 可能设置了一个 classpath and/or VM 选项,与您在终端输入的内容不同。

通过 IDE 获取 运行 的确切命令行,如果您不知道如何使用 IDE 执行此操作,您可以使用 jps 和 /proc //命令行。

例如。如果我在 运行 在 IDE 中执行我的程序时 运行 jps,我会看到:

13923 日元 11333 MyJFrame 15006 主要

我知道我的主要 class 是 MyJFrame,所以我知道我的 PID 必须是 11333。

如果我 运行 cat /proc/11333/cmdline,我得到:

/usr/local/jdk1.8.0_25/bin/java-Dfile.encoding=UTF-8-classpath/home/shackle/NetBeansProjects/JavaApplication31/build/classesjavaapplication31.MyJFrame

它缺少参数之间的空格,但很明显它们会去哪里。 运行 在终端上小心插入空格后的命令。

此外,当您 运行 jar 并且它不产生任何输出时,最好准确查看哪一行正在执行。 运行 原始命令,使用 jps 获取 pid,在该 pid 上使用 jstack 获取所有堆栈帧,包括它被阻塞的行。

我最终通过删除 defauls jar 配置并重新添加它来解决这个问题,下面的说明适用于任何使用 IntelliJ IDEA 的人。

File -> Project Structure -> Artifacts

然后使用小 minus 按钮删除 jar 设置并使用 plus 符号重新添加。

JAR -> From modules with dependencies -> OK