我不认为我想要使用的程序在与地震学无关的人中很有名。但我想要使用的是地震图的实用软件。 无论如何,它是一个基本上我们在shell中使用的交互式软件。
(SAC表示地震分析代码)
SAC>读"文件名"
SAC>积
然后它将创建一个显示波形的窗口。
我想通过ProcessBuilder和Process在Java中执行此操作。 我实际上并不关心我使用什么类,只是我知道他们只做这样的事情。
我创建了一个为SAC提供进程的类。 标准输出和错误分别由另一个线程读取, 当我用Google搜索它时,它告诉我们处理问题的一个可能原因是 与那些有关。 (即使SAC没有如此多地返回输出错误......)
在我启动那些threads.start()之后,我写了#34;读取文件名"和"情节" 标准输入,但没有任何反应。某个程序退出时会出现一个窗口。
这是我的代码。
public static void main(String[] args){
try(Sac sac = Sac.createProcess()){
// Class Sac governs a Process for SAC
sac.inputCMD("r abc.R");
// inputCMD is writing in standard input and flush immediately
sac.inputCMD("plot");
for (;;) // this is just for time to see what is going on
;
}
}
我会再说一遍 当我杀死Java运行时,窗口有时会弹出并很快消失。
我认为这与线程问题有关。 因为当我从另一个线程调用SAC#inputCMD(" plot")时,每次都会立即弹出一个窗口。
我在main中创建SAC是一个问题吗?
----添加---- 我提到了其他线程的顺序。但它通常不起作用......
这是Class Sac和ExternalProcess
public class Sac extends ExternalProcess implements Closeable {
Sac(Process process) {
super(process);
standardInput = new PrintWriter(super.standardInput);
}
public static Sac createProcess() throws IOException {
ProcessBuilder builder = null;
if (checkEnvironment())
builder = new ProcessBuilder("sac");
else
throw new RuntimeException("No sac in PATH or No SACAUX is set.");
return new Sac(builder.start());
}
/**
* Make an order to Sac
*
* @param line
* command line for SAC
*/
public void inputCMD(String line) {
standardInput.println(line);
standardInput.flush();
}
@Override
public void close() {
try {
standardInput.println("q");
standardInput.flush();
standardInput.close();
process.waitFor();
standardOutput.join();
standardError.join();
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean checkEnvironment() {
// String sachome = System.getenv("SACHOME");
boolean sacExistence = System.getenv("PATH").contains("/sac/bin");
String sacaux = System.getenv("SACAUX");
return sacExistence && sacaux != null;
}
/**
* Input for Sac
*/
private PrintWriter standardInput;
}
这是ExternalProcess。
public class ExternalProcess {
/**
* {@link Stream} for standard output
*/
protected InputStreamThread standardOutput;
/**
* {@link Process} for Sac
*/
protected Process process;
/**
* {@link Stream} for standard error
*/
protected InputStreamThread standardError;
/**
* connected to standard input
*/
protected OutputStream standardInput;
ExternalProcess(Process process) {
this.process = process;
standardOutput = new InputStreamThread(process.getInputStream());
standardError = new InputStreamThread(process.getErrorStream());
standardError.start();
standardOutput.start();
standardInput = process.getOutputStream();
}
public static ExternalProcess launch(String... command) throws IOException {
ProcessBuilder builder = new ProcessBuilder(command);
return new ExternalProcess(builder.start());
}
/**
* @return {@link OutputStream} connected to a standard input to the
* process
*/
public OutputStream getStandardInput() {
return standardInput;
}
/**
* @return {@link InputStreamThread} connected to a standard output to the
* process
*/
public InputStreamThread getStandardOutput() {
return standardOutput;
}
/**
* @return {@link InputStreamThread} connected to a standard error to the
* process
*/
public InputStreamThread getStandardError() {
return standardError;
}
public static ExternalProcess launch(List<String> command) throws IOException {
ProcessBuilder builder = new ProcessBuilder(command);
return new ExternalProcess(builder.start());
}
public int waitFor() {
try {
int process = this.process.waitFor();
standardError.join();
standardOutput.join();
return process;
} catch (Exception e) {
throw new RuntimeException();
}
}
}
最后是InputStreamThread
public class InputStreamThread extends Thread {
/**
* if the stream is closed
*/
private boolean closed;
/**
* Wait until the inputstream is closed and return String[]
* @return {@link String}[] from input stream
*/
public String[] waitAndGetString(){
try {
while(!closed)
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
return list.toArray(new String[list.size()]);
}
@Override
public void run() {
try(BufferedReader br = new BufferedReader(inputStreamReader)) {
for (;;) {
String line = br.readLine();
if (line == null)
break;
list.add(line);
//System.out.println(line+" "+list.size());
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally{
closed = true;
}
}
/**
* List of String from the stream
* 文字列の取得
* @return {@link List} of {@link String} from the {@link InputStream}
*/
public List<String> getStringList() {
return list;
}
private List<String> list = new ArrayList<>();
private InputStreamReader inputStreamReader;
public InputStreamThread(InputStream is) {
inputStreamReader = new InputStreamReader(is);
}
}
答案 0 :(得分:0)
所以,一个问题和一个答案。问题:你关心标准输出/标准错误的内容吗?如果你不这样做,我建议你开始使用管道,这引导我回答:
你的ExternalProcess类在那时变得更简单了(不需要乱用输入读取回显线程等)。
此外,您谈论的其他事情似乎表明多个线程可能有权访问ExternalProcess的实例 - 这意味着您应该标记您的&#34;输入&#34;方法同步。
我最终得到了这个:
package so;
import java.io.IOException;
import java.io.PrintWriter;
public class ExternalProcess {
private final Process process;
private final PrintWriter commandWriter;
public ExternalProcess(String... command) throws IOException {
process = new ProcessBuilder(command)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectInput(ProcessBuilder.Redirect.PIPE)
.start();
commandWriter = new PrintWriter(process.getOutputStream());
}
public synchronized ExternalProcess inputCMD(char... chars) {
if (chars != null && chars.length > 0) {
commandWriter.write(chars);
}
return this;
}
public synchronized ExternalProcess inputCMD(String line) {
commandWriter.println(line);
commandWriter.flush();
return this;
}
public void waitFor() throws InterruptedException {
process.waitFor();
}
public void stop() {
process.destroy();
}
}
然后我写了一个小测试来推送我的常规shell,包括用VI做一些无意义的编辑。
package so;
import java.io.IOException;
public class TestMain {
public static void main(String... args) throws IOException, InterruptedException {
ExternalProcess externalProcess = new ExternalProcess("/bin/bash");
externalProcess.inputCMD("ls -lah");
externalProcess.inputCMD("rm /tmp/foo");
externalProcess.inputCMD("vi /tmp/foo");
externalProcess.inputCMD("i hello world.");
externalProcess.inputCMD((char) 0x1B);
externalProcess.inputCMD(":wq!");
}
}
似乎工作正常。
如果您遇到问题&#34; sac&#34;作出回应 - 它可能与某些奇怪的方式中的期待事物/ dev / tty有关。
请注意,其中一些不可避免的特定于平台 - 如果你的能力不同而不是在一个不合适的世界中,我会把这个转化为你的宇宙,为读者做一个练习。