12.6 Java虚拟机读写其他进程的数据

一、回顾

回顾Java的Runtime类可以单独启动一个进程来运行操作系统的命令,如下程序所示:

package section6;

public class ExecTest
{
    public static void main(String[] args)
        throws Exception
    {
        //程序不能创建自己的Runtime实例,但是可以通过getRuntime()
        //获取与之相关联的Runtime实例
        var rt=Runtime.getRuntime();
        //运行记事本
        rt.exec("notepad.exe");
    }
}

二、Runtime对象的exec()产生Process对象的

使用Runtime对象的exec()方法可以运行平台上的其他程序,该方法产生一个Process对象,Process对象代表由该Java程序启动子进程。Process对象提供了如下三个方法,用于让程序和其他子进程之间进行通信。
★InputStream getErrorStream():获取子进程的错误流。
★InputStream getInputStream():获取子进程的输入流。
★OutputStream getOutputStream():获取子进程的输出流。
注意:如果试图让子进程读取程序中的数据,那么应该使用输出流。要站在Java角度来看问题,子程序读取Java程序的数据,就是让Java程序把数据输出到子进程中(就像把数据输出到文件中一样,只是由子进程节点代替了文件节点),所以应该使用输出流。

2.1 获取子程序的输出流作为本程序的输入流

下程序示范了读取其他进程的输出信息:

package section6;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class ReadFromProcess
{
    public static void main(String[] args)
        throws Exception
    {
        //运行javac命令,返回该命令的子进程
        Process p=Runtime.getRuntime().exec("javac");
        try(
                //以p进程的错误输出流创建BufferedRead对象
                //这个错误流对p进程是输出流,对于本程序是输入流
                //1、首先将这个错误流转换为字符流
                var cs=new InputStreamReader(p.getInputStream());
                //2、转换流转化为BufferedReader流
                var br=new BufferedReader(cs)
                )
        {
            String buff=null;
            while((buff=br.readLine())!=null)
            {
                System.out.println(buff);
            }
        }
    }
}

上面程序使用Runtime启动了javac程序,获取了运行该程序的子进程;然后以p进程的错误输入流创建了bufferedReader,这个输入流的流向如图所示:

注:以前版本的javac进程的错误输入流要通过getErrorStream()方法获取,现在改为getInputStream()方法获取。
下图所示的数据流对p进程(javac进程)而言,它是输出流;但对本程序而言,它是输入流——衡量输入输出流总是站在本程序所在的内存角度,所以数据流应该是输入流。

2.2 本程序的输出流作为子进程的输入流

可以通过Process的getOutputStream()方法获得项进程输入数据的流(该流对Java程序是输出流,对子进程则是输入流),下面程序实现了在Java程序中启动Javaxu


import java.io.*;
import java.util.*;

public class WriteToProcessplus
{
	public static void main(String[] args)
		throws IOException
	{
		// 运行java ReadStandard命令,返回运行该命令的子进程
		Process p = Runtime.getRuntime().exec("java ReadStandardplus");
		try (
			// 以p进程的输出流创建PrintStream对象
			// 这个输出流对本程序是输出流,对p进程则是输入流
			var ps = new PrintStream(p.getOutputStream()))
		{
			// 向ReadStandard程序写入内容,这些内容将被ReadStandard读取
			ps.println("普通字符串");
			ps.println(new WriteToProcessplus());
		}
	}
}
// 定义一个ReadStandard类,该类可以接受标准输入,
// 并将标准输入写入out.txt文件。
class ReadStandardplus
{
	public static void main(String[] args)
	{
		try (
			// 使用System.in创建Scanner对象,用于获取标准输入
			var sc = new Scanner(System.in);
			var ps = new PrintStream(new FileOutputStream("out.txt")))
		{
			// 增加下面一行将只把回车作为分隔符
			sc.useDelimiter("\n");
			// 判断是否还有下一个输入项
			while (sc.hasNext())
			{
				// 输出输入项
				ps.println("键盘输入的内容是:" + sc.next());
			}
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
		}
	}
}

在WriteToProcess中使用Runtime的exec()方法来运行java ReadStandard命令,该命令将运行ReadStandard类,并返回该程序的子进程。var ps = new PrintStream(p.getOutputStream())获取子进程的p的输出流——该输出流对于p进程是输入流,对于本程序是输出流。本程序通过该输出流向进程p中输入数据。

运行后将看到一个out.txt文档,内容为:

posted @ 2020-05-01 20:01  小新和风间  阅读(576)  评论(0编辑  收藏  举报