命令行终端执行进程并从此进程输入交互

Dam*_*iii 9 java process

基本上,我在我的java应用程序上按下按钮时会运行一个进程.并且该过程向OS的终端执行命令.但有时这个命令需要与用户进行交互.我想知道是否可以在需要时从流程到用户进行交互?

我的代码:

File marsSimulator = new File("resources/mars_simulator/Mars4_5.jar");
if(marsSimulator.exists() && temp.exists()){
   String res="";
   try {
     Process p = Runtime.getRuntime().exec(new String[]{"java","-jar",marsSimulator.getAbsolutePath(),tempAssembly.getAbsolutePath()});
     p.waitFor();

     InputStream is = p.getInputStream();

     byte b[] = new byte[is.available()];
     is.read(b, 0, b.length); // probably try b.length-1 or -2 to remove "new-line(s)"

     res = new String(b);

   } catch (Exception ex) {
     ex.printStackTrace();
   }
}
Run Code Online (Sandbox Code Playgroud)

另外,我忘了说应用程序是用SWING制作的,并且进程的输出显示在TextArea上......我应该改变什么吗?

请注意,当与用户进行交互时,进程会阻止.如果没有,则该过程不会阻止!

在这种情况下我需要做什么(我不知道该怎么做)?

  1. 当流程需要交互时.我需要知道这个过程何时需要一些互动.
  2. 我需要以交互方式(逐行)获得流程生成的输出.

PS:对于想要了解流程线的人,我使用的是火星模拟器(http://courses.missouristate.edu/KenVollmar/MARS/),我将jar应用程序发送到一个与mips汇编代码相关联的流程中.


下一段代码正在处理我的项目

希望它能为下一位冒险者提供帮助!

感谢Nicolas Filotto帮助我.

我的班级ObservableStream:

class ObservableStream extends Observable {
  private final Queue<String> lines = new ConcurrentLinkedQueue<>();

  public void addLine(String line) {
    lines.add(line);
    setChanged();
    notifyObservers();
  }

  public String nextLine() {
    return lines.poll();
  }

  public String getLine(){return lines.peek();}
}
Run Code Online (Sandbox Code Playgroud)

而代码的另一部分:

Process p = Runtime.getRuntime().exec(new String[]{"java","-jar",marsSimulator.getAbsolutePath(),tempAssembly.getAbsolutePath()});

//This code does the interaction from the process with the GUI ! Implied, input interaction+output interaction from the process
ObservableStream out = new ObservableStream();
// Observer that simply sends to my external process line by line what we put in
// the variable output
PrintWriter writer = new PrintWriter(p.getOutputStream(), true);
out.addObserver(
  (o, arg) -> {
    ObservableStream stream = (ObservableStream) o;
    String line;
    while ((line = stream.nextLine()) != null) {
      writer.println(line);
    }
  }
);

ObservableStream input = new ObservableStream();
input.addObserver(
  (o, arg) -> {
    ObservableStream stream = (ObservableStream) o;
    String line;
    while ((line = stream.nextLine()) != null) {
      outputTextArea.appendText(line+"\n");
    }
  }
);

// The thread that reads the standard output stream of the external process
// and put the lines into my variable input
new Thread(
  () -> {
    try (BufferedReader reader = new BufferedReader(
      new InputStreamReader(p.getInputStream()))
    ) {
       String line;
       while ((line = reader.readLine()) != null) {
         input.addLine(line);
      }
    } catch (IOException e1) {
      e1.printStackTrace();
  }
 }
).start();


new Thread(
  ()->{
    while(p.isAlive()){
      String res = input.getLine();
      if(res!=null && res.equals("Enter integer value:")) {
        boolean integerIsRequested=true;
        Thread t=null;
        while(integerIsRequested){
          if(t==null) {
            t = new Thread(new Runnable() {
              public void run() {
                String test1 = JOptionPane.showInputDialog("Enter Integer value:");
                while(!test1.matches("^\\d+$")){
                  test1 = JOptionPane.showInputDialog("Error: Not a valid Integer.\nEnter a correct Integer value:");
                }
                Integer i = Integer.valueOf(test1);

                if (i != null) {
                  out.addLine(test1);
                }
              }
            });
            t.start();

          }
          if(!t.isAlive()){
            integerIsRequested=false;
          }
        }
      }
    }
    outputTextArea.appendText("Program executed\n");
  }
).start();
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这篇文章是独一无二的Jarrod;)

Nic*_*tto 5

为了实现这样的用例,我个人会使用:

  1. Observable当外部进程提供新行时通知我的UI 的对象
  2. Observable我添加由UI提供的新行的对象
  3. Observer#1,将刷新我的UI的数据
  4. 一个Observer#2,将我的UI提供的线路发送到我的外部进程
  5. A Thread将检查我的外部进程是否提供了新行,如果是,则将这些行提供给#1

因为我没有完整的环境,我将向您展示它如何与模拟对象一起使用:

首先,我的假外部应用程序只执行Echo他收到的内容:

public class Echo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            String line = scanner.nextLine();
            System.out.printf("echo > %s%n", line);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果此类接收foo,它将打印到标准输出流中echo > foo

然后我的Observable班级

public class ObservableStream extends Observable {
    private final Queue<String> lines = new ConcurrentLinkedQueue<>();

    public void addLine(String line) {
        lines.add(line);
        setChanged();
        notifyObservers();
    }

    public String nextLine() {
        return lines.poll();
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:这个班级ObservableStream(目前为止实施)只是Observer根据你的需要,只有一个不足够.实际上,它仅用于将UI与数据的检索或发布方式分离

最后主要代码:

Process p = Runtime.getRuntime().exec(
    new String[]{"java", "-cp", "/my/path/to/my/classes", "Echo"}
);
// The Observable object allowing to get the input lines from my external process
ObservableStream input = new ObservableStream();
// A mock observer that simply prints the lines provided by the external process
// but in your case you will update your text area instead
input.addObserver(
    (o, arg) -> {
        ObservableStream stream = (ObservableStream) o;
        String line;
        while ((line = stream.nextLine()) != null) {
            System.out.printf("Line Received from the external process: %s%n", line);
        }
    }
);
// The thread that reads the standard output stream of the external process 
// and put the lines into my variable input
new Thread(
    () -> {
        try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(p.getInputStream()))
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                input.addLine(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
).start();
// The Observable object allowing to send the input lines to my external process
ObservableStream output = new ObservableStream();
// Observer that simply sends to my external process line by line what we put in
// the variable output
PrintWriter writer = new PrintWriter(p.getOutputStream(), true);
output.addObserver(
    (o, arg) -> {
        ObservableStream stream = (ObservableStream) o;
        String line;
        while ((line = stream.nextLine()) != null) {
            writer.println(line);
        }
    }
);

// A simple scanner used to send new messages to my external process
Scanner scanner = new Scanner(System.in);
while (true) {
    output.addLine(scanner.nextLine());
}
Run Code Online (Sandbox Code Playgroud)

如果此代码收到foo,它将打印到标准输出流中Line Received from the external process: echo > foo