基本上,我在我的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上......我应该改变什么吗?
请注意,当与用户进行交互时,进程会阻止.如果没有,则该过程不会阻止!
在这种情况下我需要做什么(我不知道该怎么做)?
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;)
为了实现这样的用例,我个人会使用:
Observable当外部进程提供新行时通知我的UI 的对象Observable我添加由UI提供的新行的对象Observer#1,将刷新我的UI的数据Observer#2,将我的UI提供的线路发送到我的外部进程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
| 归档时间: |
|
| 查看次数: |
1103 次 |
| 最近记录: |