锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / Java开源技术 / Java调用外部进程
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品开源,禁止转载和任何形式的非法内容使用,违者必究。本文仅进行了翻译,如果需要实际技术请联系锐英源。


Java调用外部进程

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:

  • Input and Output streams from and to the process aren't handled properly.
  • Although the Process is running, your application isn't waiting for it to finish.
  • Your application IS waiting for the process to finish by simply halting.
  • The process terminated, but you did not receive the result code.
  • You simply have no idea how to actually run an External Process!

有时,当您依赖Java代码执行外部进程时,实际上正确运行代码可能会非常痛苦。
尝试运行外部进程时有几个缺陷:

  1. 源进程的输入和目标进程的输出未得到正确处理。
  2. 虽然进程正在运行,但您的应用程序并没有等待它完成。
  3. 您的应用程序是否正在等待该过程完成,只需停止即可。
  4. 该进程终止,但您没有收到结果代码。
  5. 您根本不知道如何实际运行外部进程!

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:

  • Reusable code
    • dev.exec.util.ExecHelper
    • dev.exec.util.ExecProcessor
  • Demo code
    • dev.exec.tester.TestApplication
    • dev.exec.tester.TestFrame

如果这些问题中的任何一个给您带来麻烦,请继续阅读。
我将使用DOS提示符(在WinXP下)作为本文演示的外部过程。
来源包括如下:

  • 可重复使用的代码
    • dev.exec.util.ExecHelper
    • dev.exec.util.ExecProcessor
  • 演示代码
    • dev.exec.tester.TestApplication
    • dev.exec.tester.TestFrame
    •  

The idea is simple:

  • TestApplication creates an instance of TestFrame.
  • TestFrame is displayed to the user.
  • The user requests the execution of the Command Processor.
  • TestFrame registers itself to the ExecHelper as an ExecProcessor.
  • TestFrame uses the ExecHelper to run the Command Processor.
  • ExecHelper notifies the TestFrame about new output text.
  • The user uses the TestFrame to input commands for the Command Processor.
  • TestFrames notifies the ExecHelper about new user input.
  • ExecHelper notifies the Command Processor about new user input.
  • While the Command Processor is running, loop through 6 - 10.
  • While the program is running, loop through 3 - 11.
  • Quit.

这个想法很简单:

  • TestApplication 创建一个实例TestFrame。
  • TestFrame 显示给用户。
  • 用户请求执行命令。
  • TestFrame 将自己注册到ExecHelper,成为ExecProcessor。
  • TestFrame 使用它ExecHelper 来运行命令。
  • ExecHelper 通知TestFrame 新的输出文本。
  • 用户使用TestFrame 命令处理器的输入命令。
  • TestFrames 通知ExecHelper 新用户输入。
  • ExecHelper 通知命令有关新用户输入的信息。
  • 当命令运行时,循环6到10。
  • 程序运行时,循环3 - 11。
  • 退出。

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 processNewInput(String input) {
updateTextArea(jTextArea1, input);
}

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()由此方法执行该命令,如下面的代码说明了:


void runCommandActionPerformed(ActionEvent e) {
if (exh == null) {
try {
exh = ExecHelper.exec(this, "cmd.exe");
statusBar.setText("Command.exe running..");
} catch (IOException ex) {
processNewError(ex.getMessage());
}
}

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功能的人都有用。

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内