精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
锐英源精品开源,禁止转载和任何形式的非法内容使用,违者必究。本文仅进行了翻译,如果需要实际技术请联系锐英源。
Introduction
Sometimes, when you depend on the execution of External Processes from your Java code, it can be a real pain to actually get that code running properly.
There are several pitfalls while trying to run external processes:
有时,当您依赖Java代码执行外部进程时,实际上正确运行代码可能会非常痛苦。
尝试运行外部进程时有几个缺陷:
If any of these problems ever troubled you, read on.
I will use the DOS prompt (under WinXP) as an External Process for this article's demonstration.
The sources are composed as follows:
如果这些问题中的任何一个给您带来麻烦,请继续阅读。
我将使用DOS提示符(在WinXP下)作为本文演示的外部过程。
来源包括如下:
The idea is simple:
这个想法很简单:
The source files are documented (at least the ExecHelper and ExecProcessor), and the demo ZIP contains a JBuilder project and the compiled classes plus a JAR file.
I will now explain how the concept is put to work in the Reusable code.
First off, I declared ExecProcessor as an interface to handle all the events coming from the External Process.
源文件被记录(至少是ExecHelper 和ExecProcessor),并且演示ZIP包含JBuilder 项目和已编译的类以及JAR文件。
我现在将解释如何在可重用代码中使用该概念。
首先,我声明ExecProcessor 为处理来自外部进程的所有事件的接口。
public interface ExecProcessor {
// This method gets called when the process sends us a new input String..
public void processNewInput(String input);
// This method gets called when the process sends us a new error String..
public void processNewError(String error);
// This method gets called when the process has ended..
public void processEnded(int exitValue);
}
TestFrame which implements the ExecProcessor interface has the following methods:
TestFrame 实现ExecProcessor 接口的方法,如下形式:
public void processNewError(String error) {
updateTextArea(jTextArea1, error);
}
public processEnded(int exitValue) {
exh = null;
statusBar.setText("Command.exe ended..");
JOptionPane.showMessageDialog(this, "Exit value for Command.exe was ["
+ exitValue + "]", "Command.exe is done!", JOptionPane.INFORMATION_MESSAGE);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
jTextArea1.setText(null);
statusBar.setText("Ready..");
}
As you see, things are kept simple. The methods processNewInput() and processNewError() update a TextArea with the new line of text sent from the Command Processor, while the processEnded() method notifies the program that the Command Processor has terminated, and displays the exit value sent from the Command Processor.
The TestFrame itself uses the runCommandActionPerformed() method to invoke the ExecHelper's exec() method thus executing the Command Processor as the following code demonstrates:
如你所见,事情很简单。processNewInput()方法和processNewError()更新 TextArea,使用的新文本来自命令 ,同时processEnded()方法通知程序命令处理已终止,并显示从命令处理器发送的退出值。
TestFrame 本身使用runCommandActionPerformed()方法调用ExecHelper的exec()由此方法执行该命令,如下面的代码说明了:
All that is really left is to describe how the ExecHelper performs its magic. First the ExecHelper is a Runnable object, which means it has a run() method which lets it perform its tasks while the application itself keeps running (i.e. multi-threading).
ExecHelper has three streams to handle, and three Threads to work with. Yes, this version of the code requires that three separate Threads be activated for each Process. There probably is a way to do this with less, but currently I haven't had the time to research it yet.
As a Runnable object, the ExecHelper's run() method is the most interesting:
真正剩下的就是描述如何发挥ExecHelper 其魔力。首先,ExecHelper 是一个Runnable 对象,这意味着它有一个run()方法,让它在应用程序本身保持运行时执行其任务(即多线程)。
ExecHelper 有三个要处理的流,以及三个要处理的线程。是的,此版本的代码要求为每个进程激活三个单独的线程。可能有一种方法可以用更少的方式来做到这一点,但目前我还没有时间去研究它。
作为一个Runnable 对象,该ExecHelper的run()方法是最有趣的:
public void run() {
// Are we on the process Thread?
if (processThread == Thread.currentThread()) {
try {
// This Thread just waits for the process to end and notifies the handler..
processEnded(process.waitFor());
} catch (InterruptedException ex) {
ex.printStackTrace();
}
// Are we on the InputRead Thread?
} else if (inReadThread == Thread.currentThread()) {
try {
// Read the InputStream in a loop until we find no more bytes to read..
for (int i = 0; i > -1; i = pInputStream.read(inBuffer)) {
// We have a new segment of input, so process it as a String..
processNewInput(new String(inBuffer, 0, i));
}
} catch (IOException ex) {
ex.printStackTrace();
}
// Are we on the ErrorRead Thread?
} else if (errReadThread == Thread.currentThread()) {
try {
// Read the ErrorStream in a loop until we find no more bytes to read..
for (int i = 0; i > -1; i = pErrorStream.read(errBuffer)) {
// We have a new segment of error, so process it as a String..
processNewError(new String(errBuffer, 0, i));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
I leave you to look at the source code and find out for yourself how the user input flows from TestFrame to the Command Processor.
I hope this will be useful to anyone who needs this functionality in Java.
我让您看一下源代码,亲自了解用户输入如何从TestFrame 命令处理器流出。
我希望这对任何需要Java功能的人都有用。