我正在尝试编写一个java程序来启动多个进程,并将stdin重定向到主程序,同时将这些进程的输出读取到stdout。
目前我正试图启动 vlc
进程和以后计划使用不同的键盘键分别控制它们,但我想了解如何使其适用于任何进程,例如命令行或自定义telnet客户端,这样您就可以生成两个命令行并向它们发送相同的命令输入,或者以编程方式替换每个进程的部分命令。
我遇到的问题是,无法预测何时发送哪一端,所以我需要一个双向管道,或者两个管道同时运行。我还没能想出如何做到这一点,我所做的一切都让它挂起等待来自任何一种方式的输入。
我可以启动两个 vlc
进程,甚至读取它们的两个输出,但是如果进程没有挂起等待输入,我就不能将stdin发送给它们。
我已经知道了:
父类:
package multiVLC;
import java.nio.file.Path;
import java.nio.file.Paths;
public class multiVLC {
public static void main(String[] args) {
Path video1 = Paths.get("C:\\path\\to\\video1.mkv");
Path video2 = Paths.get("C:\\path\\to\\video2.mkv");
new VLCProcess(video1).start();
new VLCProcess(video2).start();
}
}
以及过程:
package multiVLC;
import java.io.*;
import java.nio.file.Path;
import java.util.Scanner;
public class VLCProcess extends Thread {
private Path videofile;
public VLCProcess(Path videofile) {
this.videofile = videofile;
}
public void run() {
try {
String[] cmd = {"C:\\Program Files\\VideoLAN\\VLC\\vlc.exe", videofile.toRealPath().toString()};
ProcessBuilder ps = new ProcessBuilder(cmd);
ps.redirectErrorStream(true); // combine stdErr and stdOut
Process pr = ps.start();
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(pr.getOutputStream()));
BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
String line;
Scanner scanin = new Scanner(in);
Scanner scansysin = new Scanner(sysin);
while (true) { // THIS HANGS
if (scanin.hasNextLine()) {
System.out.println(this.getName() + ":" + scanin.nextLine());
}
if (scansysin.hasNextLine()) {
out.write(scansysin.nextLine());
}
System.out.println("still in loop"); // NEVER PRINTS
}
// while ((line = in.readLine()) != null) { // THIS WORKED TO RUN TWO VLC PROCESSES, BUT DOESN'T REDIRECT STDIN
// System.out.println(this.getName() + ":" + line);
// }
// pr.waitFor(); // not sure if this is needed
} catch (IOException e) {
e.printStackTrace();
}
}
}
如何正确处理两种方式的管道?
1条答案
按热度按时间66bbxpm51#
要将程序的输入重定向到多个进程的输出,可以尝试以下代码,希望这些代码能够满足您的要求:
基本上,程序的主线程负责获取用户输入,然后通过一个简单的循环将用户的输入转发到所有存储进程的输出。
每个派生进程的输入都在它自己的线程中处理,因此您应该确保同步它们,以防它们之间共享资源。
System.out
确实是在进程之间共享的,因为在这段代码中,我只是将所有进程的输入打印到它,但不用担心,因为PrintStream
的方法已经同步,所以您不会得到字节交错,但您将得到行交错。你不需要导出
InputStream
每个的StartedProcess
我建议你不要这样做,因为它是在Runnable
这就是它的目的。您可以将其编码为
ExecutorService
对于Runnable
s、 以及如何处理Exception
这是适当的。编辑1:
我忘了提到,您可能会将输入与进程的输出交织在一起,这是因为当您在cli中键入时,进程将同时向其写入。