赛迪网 > IT技术 Java > 技术动态
  IT资讯搜索
 
IT产品搜索
[程序开发][网管世界][网络安全][数据库技术]
[操作系统][嘉宾聊天·在线访谈][活动集锦]
[精彩专题][Symantec专区][订阅IT技术周刊]
[开发论坛][网管论坛][安全论坛][数据库论坛]
[操作系统论坛][Sybase专区][IBM dW技术专区]
[病毒求助][病毒与漏洞播报][文档·源码下载]

Java语言中运行其它程序方法的实例详解

发布时间:2007.12.07 04:52     来源:赛迪网    作者:执木

由于前段时间一个网友写信询问如何在运行其他可执行程序时将控制台的输入提交到它想运行的程序,由于考虑到他的特殊情况就帮他弄了一下,刚开始想着这个问题应该比较简单,但是在实际做的过程中才发现有很多陷阱,而且好像不能弄一个非常通用的东西出来。下面的代码是我想做出的一个通用封装器的尝试:

 

import java.io.*;

public class CommandWrapper
{
Process process;
Thread in;
Thread out;
public CommandWrapper(Process process)
{
this.process = process;
final InputStream inputStream
= process.getInputStream();
//final BufferedReader
r=new BufferedReader
(new InputStreamReader(inputStream));
final byte[] buffer = new byte[1024];
out = new Thread()
{
//String line;
int lineNumber=0;
public void run()
{
try {
while (true)
{
int count = inputStream.read(buffer);
System.out.println
(lineNumber+":"+new String
(buffer, 0, count-1));
//line=r.readLine();
//System.out.println
(lineNumber+":"+line);
lineNumber++;
}
}
catch (Exception e)
{

}
}
};
final BufferedReader reader =
new BufferedReader
(new InputStreamReader(System.in));
final OutputStream outputStream
= process.getOutputStream();
in = new Thread()
{
String line;
public void run()
{
try {
while (true)
{
outputStream.write(
(reader.readLine()+"\n").getBytes());
outputStream.flush();
}
}
catch (Exception e)
{

}
}
};
}

public void startIn()
{
in.start();
}

public void startOut()
{
out.start();
}

public void interruptIn()
{
in.interrupt();
}

public void interruptOut()
{
out.interrupt();
}

public static void main(String[] args)
{
try
{
CommandWrapper command =
new CommandWrapper(Runtime.getRuntime().
exec("native2ascii"));
command.startIn();
command.startOut();
}
catch (Exception e) {
e.printStackTrace();
}
}

}


  我以native2ascii为范例程序和网友给我的那个程序做了对比,发现如下几个在处理这个问题时需要注意的地方:

  1、由于不知道目标程序的输入输出顺序,因此只能建立两个单独的线程分别处理输入和输出,这样输入和输出就不会阻塞了。但是有些目标程序要求有特定的输入输出顺序,而经过这个类封装的结果是在任何状态下都可以输入,程序的任何输出也会被马上反映出来,构造通用类的第一个问题。

  2、不能直接使用I/O重定向,在最开始的时候我是考虑直接使用I/O重定向的,但是实际的情况是Process的I/O的定义刚好和我的预想相反,我们从Process取得的InputStream实际上是它的输出,而取得的OutputStream是它的输入,这样就无法进行I/O重定向了,必须我们进行编码来读取程序的输出和写入控制台的输入。(这里的I/O重定向是指想将它的I/O直接重定向到系统的I/O)

  3、写入控制台的输入:

  outputStream.write
  ( (reader.readLine()+"\n").getBytes());
  outputStream.flush();


  这里有两个问题值得注意:第一个是我们在控制台输入一行数据以后按下回车,那么语句reader.readLine()可以正确的得到你的输入,为什么要加那个换行符呢?

  这是在测试的时候发现的问题,在以native2ascii作为例子的时候发现不加这个的话它不能得到控制台的输入,但是我在替那位网友解决的问题的时候他的程序则没有这个问题,因此猜想可能是因为有的程序要求读取的一整行的数据(例如native2ascii),而大部分的命令行程序在编码的时候读取的是整数这样的值或者其他类型的值,他们是以空格或者其他的字符分隔的,因此就不需要那个额外的换行符(例如那位网友的程序读取的是一元二次方程的三个系数)。

  另外一个问题就是flush方法的使用,在最开始的时候没有想到要这样刷新进去,无论是否加换行符外部程序都无法读取写入的输入,后来才想到要调用一下这个方法。这个也是在我们输出的时候应该注意的一个问题,有些需要马上反应出来的输出一般都在写入以后要调用它,否则输出/输入不能马上反应出来。 

  4、对于程序的输出,最开始我是构造的一个BufferedReader想以行为单位输出,对于那位网友的程序,结果证明不是很好用,但是以native2ascii作为例子运行又没有问题。这个估计和外部程序的代码也有关系,如果外部程序没有输出换行符可能使用BufferedReader就会有问题。但是通过直接读取输出就没有问题了。另外需要注意的就是:

  System.out.println(lineNumber+":"+new
  String(buffer, 0, count-1));


  中严格来说应该是:

  System.out.println(lineNumber+":"+
  new String(buffer, 0, count));


  之所以减一是因为读取输入的时候人为的多加了一个换行符,如果这个地方不减一就会多输出一个空行。

  基于以上的种种原因,要构造一个执行外部程序的包装器类不太好办,特别是文章中提到的几个问题。有时间和兴趣的朋友可以做一下测试,看看以上的问题和猜测是否正确。另外附上网友的源代码,是一个fortran的程序:

implicit none
real a,b,c
real d
real root1,root2
print*,'请输入一元二次方程的系数a,b,c:'
read(*,*) a,b,c
d=b**2-4.0*a*c
if(d>=0.0) then
root1=(-b+sqrt(d))/(2.0*a)
root2=(-b-sqrt(d))/(2.0*a)
print*,'root1=',root1
print*,'root2=',root2
else
print*,'一元二次方程没有实根!'
end if
pause
end


  在最开始给出的那个类虽然在某些应用中可能存在问题,但是对于一般的程序可能问题不是很大,当然大家可以根据上面的说明、猜测在应用在自己的项目中的时候进行一些修改和测试。 
   (责任编辑:包春林)


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· 简单谈谈4种类型的JDBC驱动程序 (12-06) · Ajax优于JSF的原因 (12-06)
· Java基础:看Web会话状态是如何维持的 (12-05) · 谈谈在jsp中如何用JDBC连接各种数据库 (12-05)
· 程序员必读--在java里读取大对象数据 (12-05) · JAVA进阶--看XML配置文件的读取处理 (12-05)
· 基础:Java中文问题详解,底层编码解剖 (12-05) · 浅谈 JAVA 中用动态代理类实现记忆功能 (12-05)
· java做的比较完善的FTP连接上传下载文件 (12-05) · 谈论如何用开源软件构建 java 编程环境 (12-05)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
  赛迪推荐  
  手机·资费 ·新品·导购·评测·手机资费·宽带
手机搜索  诺基亚 N73 MOTO Z6
  IT产品 ·笔记本·台式机·服务器·打印·投影
IT产品搜索 
  IT技术 ·开发·网管·安全·数据库·操作系统
  信息化 ·热点·专题·访谈·周刊·方案案例
· 网银交易收费 我国银行业如何达国际化标准
· 家庭信息化普及率提高 网上缴费成为新时尚
· 五条黄金准则能够让CIO巧妙加薪 CIO焦虑调查
· 网上书店解决方案 深圳边检指挥中心ITSM项目
  IT博客 ·曾剑秋·项立刚·Java学习·网管
  IT技术论坛 ·开发·网管·安全·数据库·系统