将程序输出重定向为输入 - 管道不工作
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
我使用 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