Java调用外部程序解决方案

关键字 Java 外部程序 CMD 进程 调用 Process

最近接触一个需求,是利用Java调用本地命令行程序,并希望Java程序能与该命令行程序进行交互,Java对该程序的操作如同在终端中对程序的操纵一样。

在技术调研的过程中,遇到了几个问题:

  • 如何Java调用命令行程序
  • 如何利用Java向命令行程序的标准输入写入字符流
  • 如何利用Java即时地得到命令行程序的标准输出流。
  • 如何利用Java即时地得到命令行程序的标准错误流

一、调用命令行程序

这个很简单,Java调用的方法为

   Process process = Runtime.getRuntime().exec(“command name”);

Process的JavaDoc地址:http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Process.html

二、标准输出

注意,在这里标准输出指的是Java程序以标准输出的方式发出字节流,这些字节流会以标准输入的方式进入被调用的命令行程序

OutputStream pOutputStream = process.getOutputStream();

PrintWriter outputWriter = new PrintWriter(pOutputStream, true);

outputWriter.print(string);

PrintWriter的第二个构造参数一定要选为true,这样才能自动flush进入外部程序,不然,没有Flush,你向被调用程序所写的输入,只有在下一次缓冲被Flush的时候才能发挥作用,这样,当你的输入很少时,你虽然在代码里print了命令,但是外部程序并没有得到他,就一直阻塞,这是开发者经常会遇到的问题。

三、标准输入和错误输入

private InputStream pErrorStream = process.getErrorStream();
private InputStream pInputStream =process.getInputStream();

这两个输入是用来接受外部程序的反馈的,外部程序通常会向标准终端打印字符,这些字符会通过这两个流得到,经过测试,我们发现一个问题,如果外部程序在输出信息时,没有用flush也会出现问题,比如C语言的程序

scanf(“%d”, &i);

printf(“%d”, i);

这段代码在运行时,虽然在终端里会即时的显示出来,但是却不能及时地发送给pInputStream,这是因为程序输出使用了缓冲机制造成的,所以,这造成的困难是如果你没有外部程序的源码,你就很难将输出即时显示出来,我目前还没有找到解决方案,如果你有源码就好办了,在源码中设置输出为即时flush就好了,我用笨办法来说明:

scanf(“%d”, &i);

printf(“%d”, i);

fflush(stdout);

这样,fflush(stdout)之后,pInputStream就会得到输入了。

四、综合

下面我们用三个线程来进行一个简单的与外部程序的交互过程的设计

线程一、

process.waitFor(),负责建立线程并等待线程结束

线程二、

for (int i = 0; i > -1; i = pInputStream.read(inBuffer)) {
                    // We have a new segment of input, so process it as a String..
                    System.out.print(new String(inBuffer, 0, i));
}

负责接收外部程序的输出信息

线程三、
                // 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..
                    Systerm.err.print(new String(errBuffer, 0, i));
                }
负责接收外部程序的错误输出信息

在适当的地方,调用outputWriter.print(string);向程序写入字符流。

推荐参考资料

http://www.codeproject.com/KB/java/ProcessHelper.aspx?display=PrintAll&fid=37239&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=1605771

posted on   邓范鑫  阅读(5899)  评论(1编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

导航

< 2009年8月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示