Java 如何使用ProcessBuilder与CLI程序持续交互

Java 如何使用ProcessBuilder与CLI程序持续交互,java,processbuilder,Java,Processbuilder,我定期使用通过docker容器访问的CLI程序。一旦我进入容器,我就可以开始使用我的CLI程序了。我遇到的问题是我想继续与同一个命令行实例交互。基本上,我正在尝试创建一个GUI程序,它将在CLI程序的“顶部”运行。我只是不知道如何继续向同一CLI实例发送命令: List<String> command = new ArrayList<String>(); command.add("cmd.exe" ); command.add("/c"); command.add("do

我定期使用通过docker容器访问的CLI程序。一旦我进入容器,我就可以开始使用我的CLI程序了。我遇到的问题是我想继续与同一个命令行实例交互。基本上,我正在尝试创建一个GUI程序,它将在CLI程序的“顶部”运行。我只是不知道如何继续向同一CLI实例发送命令:

List<String> command = new ArrayList<String>();
command.add("cmd.exe" );
command.add("/c");
command.add("docker-compose up -d");
System.out.println(command);

ProcessBuilder builder = new ProcessBuilder(command);
builder.inheritIO();
Map<String, String> environ = builder.environment();

Process process = builder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
    System.out.println(line);
}
command.clear();
command.add("cmd.exe" );
command.add("/c");
command.add("docker ps");
System.out.println(command);

process = builder.start();
is = process.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
    System.out.println(line);
}
List命令=新建ArrayList();
command.add(“cmd.exe”);
命令。添加(“/c”);
add(“docker compose up-d”);
System.out.println(命令);
ProcessBuilder=新的ProcessBuilder(命令);
builder.inheritIO();
Map environ=builder.environment();
Process=builder.start();
InputStream=process.getInputStream();
InputStreamReader isr=新的InputStreamReader(is);
BufferedReader br=新的BufferedReader(isr);
弦线;
而((line=br.readLine())!=null){
系统输出打印项次(行);
}
command.clear();
command.add(“cmd.exe”);
命令。添加(“/c”);
添加命令(“docker ps”);
System.out.println(命令);
process=builder.start();
is=process.getInputStream();
isr=新的InputStreamReader(is);
br=新的缓冲读取器(isr);
而((line=br.readLine())!=null){
系统输出打印项次(行);
}
但这不是我想要的方式。在上面,您将看到我正在运行两个命令:
docker compose up-d
,然后是
docker ps
。但我不认为它们在同一个实例中运行。因此,如果我在第一个命令中更改目录,它将不会记住第二个命令的目录


而且,它似乎在以与代码中的顺序相反的顺序运行我的命令。

我认为类
ProcessBuilder
的实例是短期的。我不认为每次创建一个新进程都会浪费内存或其他资源,但我只是猜测

在任何情况下,要重用一个
ProcessBuilder
实例来执行多个进程,只需使用它的方法,如

我编写了一个小型Swing应用程序,让用户输入[操作系统]命令并显示该命令的输出。它还没有准备好生产,但我希望它足以让你走

请注意,在java代码中创建和处理应用程序既不简单也不直观。这篇文章对我帮助很大。这是一篇古老的文章,但仍然相关(同样,在我看来)。只需用class
ProcessBuilder
替换文章中对class
Runtime
的引用,因为这篇文章是在将
ProcessBuilder
添加到JDK之前编写的

这是我的应用程序的代码。请参阅上述文章,以了解
ProcessBuilder
相关代码。为了理解Swing代码,我推荐本教程

导入java.awt.BorderLayout;
导入java.awt.EventQueue;
导入java.awt.FlowLayout;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.InputStreamReader;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JSplitPane;
导入javax.swing.JTextArea;
导入javax.swing.SwingUtilities;
导入javax.swing.WindowConstants;
公共类ProcExec实现ActionListener,Runnable{
私有静态最终字符串CLEAR=“CLEAR”;
私有静态最终字符串EXIT=“EXIT”;
私有静态最终字符串RUN=“RUN”;
私有JTextArea命令输出;
私人JTEXTEXTAREA textArea;
私有进程生成器;
公共ProcExec(){
procBuilder=新的ProcessBuilder();
}
已执行的公共无效操作(ActionEvent ActionEvent){
字符串actionCommand=actionEvent.getActionCommand();
if(CLEAR.equals(actionCommand)){
textArea.setText(“”);
}
else if(EXIT.equals(actionCommand)){
系统出口(0);
}
else if(RUN.equals(actionCommand)){
试一试{
执行();
}
捕获(异常x){
x、 printStackTrace();
}
}
}
公开募捐{
createAndDisplayGui();
}
私有void createAndDisplayGui(){
JFrame=新的JFrame(“流程执行者”);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createTopPanel(),BorderLayout.PAGE_START);
添加(createCommandPanel(),BorderLayout.CENTER);
frame.add(createButtonsPanel(),BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
私有JButton createButton(字符串文本、int助记符、字符串工具提示){
JButton按钮=新JButton(文本);
按钮。设置助记符(助记符);
按钮。设置工具提示文本(工具提示);
addActionListener(这个);
返回按钮;
}
私有JPanel CreateButtonPanel(){
JPanel buttonPanel=新的JPanel();
添加(createButton(RUN,KeyEvent.VK_R,“运行输入的命令”);
添加(createButton(CLEAR,KeyEvent.VK_C,“删除输入的命令”);
添加(createButton(EXIT,KeyEvent.VK_X,“退出应用程序”);
返回按钮面板;
}
私有JSplitPane createCommandPanel(){
textArea=新的JTextArea(30,40);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane cmdScrollPane=新的JScrollPane(textArea);
commandOutput=新的JTextArea(30,80);
JScrollPane outputScrollPane=新的JScrollPane(commandOutput);
JSplitPane splitPane=新的JSplitPane(JSplitPane.HORIZONTAL_SPLIT,