2024-03-19 22:54:30 | 我爱编程网
在编写Java程序时,有时候需要在Java程序中执行另外一个程序。
1、启动程序Java提供了两种方法用来启动其它程序:
(1)使用Runtime的exec()方法
(2)使用ProcessBuilder的start()方法
不管在哪种操作系统下,程序具有基本类似的一些属性。一个程序启动后就程序操作系统的一个进程,进程在执行的时候有自己的环境变量、有自己的工作目录。Runtime和ProcessBuilder提供了不同的方式来启动程序,设置启动参数、环境变量和工作目录。
能够在Java中执行的外部程序,必须是一个实际存在的可执行文件,对于shell下的内嵌命令是不能直接执行的。
采用Runtime的exec执行程序时,首先要使用Runtime的静态方法得到一个Runtime,然后调用Runtime的exec方
法。可以将要执行的外部程序和启动参数、环境变量、工作目录作为参数传递给exec方法,该方法执行后返回一个Process代表所执行的程序。
Runtime有六个exec方法,其中两个的定义为:
public Process exec(String[] cmdarray, String[] envp, File dir)
public Process exec(String command, String[] envp, File dir)
cmdarray和command为要执行的命令,可以将命令和参数作为一个字符串command传递给exec()方法,也可以将命令和参数一个一个的方在数组cmdarray里传递给exec()方法。
envp为环境变量,以name=value的形式放在数组中。dir为工作目录。
可以不要dir参数,或者不要envp和dir参数,这样就多出了其它4个exec()方法。如果没有dir参数或者为null,那么新启动的
进程就继承当前java进程的工作目录。如果没有envp参数或者为null,那么新启动的进程就继承当前java进程的环境变量。
也可以使用ProcessBuilder类启动一个新的程序,该类是后来添加到JDK中的,而且被推荐使用。通过构造函数设置要执行的命令以及
参数,或者也可以通过command()方法获取命令信息后在进行设置。通过directory(File directory)
方法设置工作目录,通过environment()获取环境变量信息来修改环境变量。
在使用ProcessBuilder构造函数创建一个新实例,设置环境变量、工作目录后,可以通过start()方法来启动新程序,与Runtime的exec()方法一样,该方法返回一个Process对象代表启动的程序。
ProcessBuilder与Runtime.exec()方法的不同在于ProcessBuilder提供了
redirectErrorStream(boolean redirectErrorStream)
方法,该方法用来将进程的错误输出重定向到标准输出里。即可以将错误输出都将与标准输出合并。
2、Process
不管通过那种方法启动进程后,都会返回一个Process类的实例代表启动的进程,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法:
(1) void destroy()
杀掉子进程。
一般情况下,该方法并不能杀掉已经启动的进程,不用为好。
(2) int exitValue()
返回子进程的出口值。
只有启动的进程执行完成、或者由于异常退出后,exitValue()方法才会有正常的返回值,否则抛出异常。
(3)InputStream getErrorStream()
获取子进程的错误流。
如果错误输出被重定向,则不能从该流中读取错误输出。
(4)InputStream getInputStream()
获取子进程的输入流。
可以从该流中读取进程的标准输出。
(5)OutputStream getOutputStream()
获取子进程的输出流。
写入到该流中的数据作为进程的标准输入。
(6) int waitFor()
导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
通过该类提供的方法,可以实现与启动的进程之间通信,达到交互的目的。
3、从标准输出和错误输出流读取信息
从启动其他程序的Java进程看,已启动的其他程序输出就是一个普通的输入流,可以通过getInputStream()和getErrorStream来获取。
对于一般输出文本的进程来说,可以将InputStream封装成BufferedReader,然后就可以一行一行的对进程的标准输出进行处理。
4、举例
(1)Runtime.exec()
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
public class Test1 {
public static void main(String[] args) {
try {
Process p = null;
String line = null;
BufferedReader stdout = null;
//list the files and directorys under C:\
p = Runtime.getRuntime().exec("CMD.exe /C dir", null, new File("C:\\"));
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
//echo the value of NAME
p = Runtime.getRuntime().exec("CMD.exe /C echo %NAME%", new String[] {"NAME=TEST"});
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
(2)ProcessBuilder
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test2 {
public static void main(String[] args) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
String line = null;
BufferedReader stdout = null;
//list the files and directorys under C:\
list.add("CMD.EXE");
list.add("/C");
list.add("dir");
pb = new ProcessBuilder(list);
pb.directory(new File("C:\\"));
p = pb.start();
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
//echo the value of NAME
pb = new ProcessBuilder();
mand(new String[] {"CMD.exe", "/C", "echo %NAME%"});
pb.environment().put("NAME", "TEST");
p = pb.start();
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5、获取进程的返回值
通常,一个程序/进程在执行结束后会向操作系统返回一个整数值,0一般代表执行成功,非0表示执行出现问题。有两种方式可以用来获取进程的返回
值。一是利用waitFor(),该方法是阻塞的,执导进程执行完成后再返回。该方法返回一个代表进程返回值的整数值。另一个方法是调用
exitValue()方法,该方法是非阻塞的,调用立即返回。但是如果进程没有执行完成,则抛出异常。
6、阻塞的问题
由Process代表的进程在某些平台上有时候并不能很好的工作,特别是在对代表进程的标准输入流、输出流和错误输出进行操作时,如果使用不慎,有可能导致进程阻塞,甚至死锁。
如果将以上事例中的从标准输出重读取信息的语句修改为从错误输出流中读取:
stdout = new BufferedReader(new InputStreamReader(p
.getErrorStream()));
那么程序将发生阻塞,不能执行完成,而是hang在那里。
当进程启动后,就会打开标准输出流和错误输出流准备输出,当进程结束时,就会关闭他们。在以上例子中,错误输出流没有数据要输出,标准输出流中
有数据输出。由于标准输出流中的数据没有被读取,进程就不会结束,错误输出流也就不会被关闭,因此在调用readLine()方法时,整个程序就会被阻
塞。为了解决这个问题,可以根据输出的实际先后,先读取标准输出流,然后读取错误输出流。
但是,很多时候不能很明确的知道输出的先后,特别是要操作标准输入的时候,情况就会更为复杂。这时候可以采用线程来对标准输出、错误输出和标准输入进行分别处理,根据他们之间在业务逻辑上的关系决定读取那个流或者写入数据。
针对标准输出流和错误输出流所造成的问题,可以使用ProcessBuilder的redirectErrorStream()方法将他们合二为一,这时候只要读取标准输出的数据就可以了。
当在程序中使用Process的waitFor()方法时,特别是在读取之前调用waitFor()方法时,也有可能造成阻塞。可以用线程的方法来解决这个问题,也可以在读取数据后,调用waitFor()方法等待程序结束。
总之,解决阻塞的方法应该有两种:
(1)使用ProcessBuilder类,利用redirectErrorStream方法将标准输出流和错误输出流合二为一,在用start()方法启动进程后,先从标准输出中读取数据,然后调用waitFor()方法等待进程结束。
如:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test3 {
public static void main(String[] args) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
String line = null;
BufferedReader stdout = null;
//list the files and directorys under C:\
list.add("CMD.EXE");
list.add("/C");
list.add("dir");
pb = new ProcessBuilder(list);
pb.directory(new File("C:\\"));
//merge the error output with the standard output
pb.redirectErrorStream(true);
p = pb.start();
//read the standard output
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
int ret = p.waitFor();
System.out.println("the return code is " + ret);
stdout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2)使用线程
import java.util.*;
import java.io.*;
class StreamWatch extends Thread {
InputStream is;
String type;
List output = new ArrayList();
boolean debug = false;
StreamWatch(InputStream is, String type) {
this(is, type, false);
}
StreamWatch(InputStream is, String type, boolean debug) {
this.is = is;
this.type = type;
this.debug = debug;
}
public void run() {
try {
PrintWriter pw = null;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
output.add(line);
if (debug)
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public List getOutput() {
return output;
}
}
public class Test5 {我爱编程网
public static void main(String args[]) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
// list the files and directorys under C:\
list.add("CMD.EXE");
list.add("/C");
list.add("dir");
pb = new ProcessBuilder(list);
pb.directory(new File("C:\\"));
p = pb.start();
// process error and output message
StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
"ERROR");
StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
"OUTPUT");
// start to watch
errorWatch.start();
outputWatch.start();
//wait for exit
int exitVal = p.waitFor();
//print the content from ERROR and OUTPUT
System.out.println("ERROR: " + errorWatch.getOutput());
System.out.println("OUTPUT: " + outputWatch.getOutput());
System.out.println("the return code is " + exitVal);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
7、在Java中执行Java程序
执行一个Java程序的关键在于:
(1)知道JAVA虚拟机的位置,即java.exe或者java的路径
(2)知道要执行的java程序的位置
(3)知道该程序所依赖的其他类的位置
举一个例子,一目了然。
(1)待执行的Java类
public class MyTest {
public static void main(String[] args) {
System.out.println("OUTPUT one");
System.out.println("OUTPUT two");
System.err.println("ERROR 1");
System.err.println("ERROR 2");
for(int i = 0; i < args.length; i++)
{
System.out.printf("args[%d] = %s.", i, args[i]);
}
}
}
(2)执行该类的程序
import java.util.*;
import java.io.*;
class StreamWatch extends Thread {
InputStream is;
String type;
List output = new ArrayList();
boolean debug = false;
StreamWatch(InputStream is, String type) {
this(is, type, false);
}
StreamWatch(InputStream is, String type, boolean debug) {
this.is = is;
this.type = type;
this.debug = debug;
}
public void run() {
try {
PrintWriter pw = null;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
output.add(line);
if (debug)
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public List getOutput() {
return output;
}
}
public class Test6 {
public static void main(String args[]) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
String java = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
String classpath = System.getProperty("java.class.path");
// list the files and directorys under C:\
list.add(java);
list.add("-classpath");
list.add(classpath);
list.add(MyTest.class.getName());
list.add("hello");
list.add("world");
list.add("good better best");
pb = new ProcessBuilder(list);
p = pb.start();
System.out.println(mand());
// process error and output message
StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
"ERROR");
StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
"OUTPUT");
// start to watch
errorWatch.start();
outputWatch.start();
//wait for exit
int exitVal = p.waitFor();
//print the content from ERROR and OUTPUT
System.out.println("ERROR: " + errorWatch.getOutput());
System.out.println("OUTPUT: " + outputWatch.getOutput());
System.out.println("the return code is " + exitVal);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
随着科技的不断发展,计算机编程已经成为了一项重要的技能。在编程的过程中,JAVA语言已经成为了非常流行的一种编程语言。为了更好地学习和测试JAVA语言,我们需要使用JAVA模拟器。下面是2022年JAVA模拟器排行榜前十名以及好玩的JAVA模拟器大全。
1. Eclipse
Eclipse是一个非常流行的JAVA开发环境,它可以运行JAVA程序、调试和测试JAVA代码。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
2. NetBeans
NetBeans也是一个非常流行的JAVA开发环境,它可以帮助你编写、测试和调试JAVA程序。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
3. IntelliJ IDEA
IntelliJ IDEA是一个非常流行的JAVA开发工具,它可以帮助你编写、测试和调试JAVA程序。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
4. BlueJ
BlueJ是一个非常流行的JAVA开发环境,它可以帮助初学者更好地学习JAVA编程。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
5. JGrasp
JGrasp是一个非常流行的JAVA开发环境,它可以帮助你编写、测试和调试JAVA程序。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
6. DrJava
DrJava是一个非常流行的JAVA开发环境,它可以帮助你编写、测试和调试JAVA程序。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
7. JCreator
JCreator是一个非常流行的JAVA开发环境,它可以帮助你编写、测试和调试JAVA程序。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
8. Java SE Development Kit
Java SE Development Kit是一套非常重要的JAVA开发工具,它包括了JAVA开发所需要的所有工具和库。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
9. Java Runtime Environment
Java Runtime Environment是一个非常重要的JAVA开发工具,它可以帮助你运行JAVA程序和APPLET。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
10. CodeRunner
CodeRunner是一个非常流行的编程工具,它可以编写和运行多种编程语言的程序,包括JAVA。它也是一个非常好的JAVA模拟器,可以帮助你测试和调试JAVA程序。
以上是2022年JAVA模拟器排行榜前十名,它们都是非常好的JAVA模拟器,可以帮助你更好地学习和测试JAVA语言。除了以上10个模拟器,还有很多其他的好玩的JAVA模拟器,例如Greenfoot、Jython、JRuby等等。你可以根据自己的需求选择最适合自己的JAVA模拟器。
我爱编程网(https://www.52biancheng.com)小编还为大家带来用Java编写程序,设计一个模拟电梯运行的类的相关内容。
最佳答案代码如下:
public class ElevatorModel implenent ElevatorModelListener{
ElevatorShaft elevatorShaft;//电梯车箱
Floor firstFloor;
Floor secondFloor;
public void addPerson(Person person);
//实现ElevatorModelListener接口的所有方法
}
public abstract class Location{
String locationName;//可能占据的三个位置firstFloor; secondFloor;elevator中的其中一个位置。
public Button getButton();
public Door getDoor();
}
public class Floor extends Location{
public Floor(String firstFloor,String secondFloor);
public Button getButton();//具体实现
public Door getDoor();//具体实现
public ElevatorShaft getElevatorShaft();
}
public class Door implenent ElevatorMoveListener{
boolean open;//门是开的关的
public void openDoor();//开门
public viod clossDoor();//关门
}
public class Button implenent ElevatorMoveListener{
boolean pressed;
public void pressButton();//按下按钮
public void resetButton();//释放按钮
public void elevatorArrived();//电梯到来
}
public class ElevatorShaft{//电梯乘箱
Elevator elevator;//电梯
Button firstFloorButton,secondFloorButton;//出发层的按钮和到达层的按钮 Door firstFloorDoor,secondFloorDoor;//出发的门和到达的门
Light firstFloorLight,secondFloorLight;//灯
//监听器
DoorListener doorListener;
ButtonListener buttonListener;
LightListener ligthListener;
BellListener bellListener;
ElevatorMoveListener elevatorMoveListener;
Set set;
}
public class Light implenent ElevatorMoveListener{
boolean lightOn;//代表灯的状态,亮或灭
public void turnOnLight();
public void turnOffLight();
public void elevatorDeparted();//具体实现
public void elevatorArrived();//具体实现
}
public class Bell implenent ElevatorMoveListener{
public void ringBell();
public void elevatorDeparted();//具体实现
public void elevatorArrived();//具体实现
}
public class Elevator extends Location implenets
ButtonListener,DoorListener,BellListener,Runable
{//电梯乘箱
boolean moving;
boolean summoned;//描述Elevator是在移动还是已经补召唤
Floor currentFloor;//当前正在提供服务的Floor
Floor destinationFloor ; //代表将要到达的Floor
Button elevatorButton;
Door elevatorDoor;
Bell bell;
public void run();// 实现
public void requestElevator();//请求Elevator并产生排队请求。 }
public class Person extends Thread{
Location类对象(或是位于Floor上,或是出处在Elevator中); int ID;
boolean moving;
public void run();//具体实现
public void enterAndRideElevator();
}
如何用java程序操作安卓模拟器首先是电脑的java模拟器。在做测试以前在搜索引擎中将两个模拟器下载下来。自然是下载安全无毒的java模拟器。电脑使用的是exe文件但是常以rar打包。安卓智能机是apk文件。我使用的java模拟器是个绿色软件,也就是说无需安装。解压压缩包后打开文件夹。找到主运行文件点击运行。在程序主界面点击文件。选择载入jar文件。jar就是java数据文件java
java应用程序怎样打包成可jar执行程序(java打包成可执行文件)总体思路是先打成jar再把jar打成exe。主要看1.3和2.3里的内容就可以了。1.将项目打成jar:1.1要将项目打包成jar文件,方法很多,可以用Eclipse自带的打包工具Ant打包,也可以用Eclipse的Export生成jar。经过尝试后,我不推荐用Ant打包,因为要自己编写xml脚本语言,还要增
java进程虚拟内存占用高有什么影响性能问题。虚拟内存是通过将部分数据从物理内存交换到磁盘上的虚拟内存中来实现的,如Java进程的虚拟内存占用过高,会导致频繁的内存页交换,这会增加磁盘I/O操作,降低系统性能,并导致应用程序响应变慢。Java程序占用内存太高了怎么办?先看下是否有内存泄露,简单的方法就是隔一段时间检查下内存,看看是否是持续上升。然后看下资源是否可以优化,
thinkphp5怎么获取当前的模块,控制器和方法名thinkphp5系列需要获取当前的模块、控制器以及方法名称,可以使用自带的Request类,也可以使用request助手函数。接下来举例说明:假设我们现在访问的地址是index/member/add,我们来获取这个地址的模块、控制器、方法名称1、获取模块名:echo"当前模块名称是:".request()->mo
什么是java虚拟机,简述其工作机制Java虚拟机处于机器和编译程序之间,在任何平台上都提供给编译程序一个共同的接口。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。Java虚拟机的主要任务是装载class文件并且执行其中的字节码。Java虚拟机包含一个类装载器,它可以从程序
java获取运行时间很多朋友都想知道java怎么获取运行时间?下面就一起来了解一下吧~第一种是以毫秒为单位计算的。//伪代码long startTime=System.currentTimeMillis(); //获取开始时间doSomeThing(); //测试的代码段long endTime=System.currentTimeMillis(); //获取结束时间System.
简述java语言的运行机制简单来说Java程序的运行机制编写 、编译 、运行 三个步骤。运行机制主要是指编译 、运行的过程1、编译Java编译器对源文件进行错误排查的过程,编译后将生成后缀名为.class的字节码文件。好让JVM(java虚拟机)里的解释器可以正常读取。2、运行三步 代码的装入、代码的校验和代码的执行2.1、 代码
java程序乱码和服务器上操作系统的编码有关系吗这个路操作系统也有关系,如果没有指定编码,java程序就会取系统的编码,建议设置成UTF-8编码。两种在代码中解决乱码的方法:1.servlet中doGet方法:Stringname=request.getParameter("name");Stringname=newString(request.getParameter("n
2025-02-01 20:24:39
2024-01-05 14:11:24
2025-02-12 03:21:37
2025-02-10 15:19:48
2025-01-28 17:58:32
2024-11-22 05:08:01