[疯狂Java]I/O:标准流重定向、JVM读写其它进程数据
2016-04-24 14:24
357 查看
1. 标准输入输出流:
1) 标准I/O流就是指System.in、System.out、System.err这三个,分表表示标准输入流、标准输出来、标准错误流;
2) 三者默认的流节点分别是键盘、屏幕、屏幕,这也是我们频繁使用的三个I/O流;
2. 标准流重定向:
1) 即人为改变三个标准流的流节点,比如吧System.out的流节点人为改成某个文件,那么在使用System.out输出的时候就不是输出到屏幕了而是输出到那个文件了;
2) 简单地说就是改变标准流原来默认的流向而已;
3) System提供了3个静态方法对标准流重定向:
i. static void setIn(InputStream in); // 重定向标准输入流
ii. static void setOut(PrintStream out); // 重定向标准输出流
iii. static void setErr(PrintStream err); // 重定向标准错误流
!!可以看到两个输出流必须要用处理流来重定向(当然必须要确定底层的流节点),而输入流一般用一个节点流来重定向就行了;
4) 示例:分别重定向输出流和输入流
3. JVM读写其它进程的数据:
1) 我们知道可以通过Runtime.getRuntime().exec(String cmd)在当前进程中执行平台上的另一个子进程,该方法返回代表该子进程句柄的Process对象;
2) 现在我们要做的就是父子两个进程之间进行通信(数据交流);
3) Process对象提供了三个方法来达到上述目的:三个方法均以当前进程(即父进程)为视角出发的
i. InputStream Process.getInputStream(); // 获得子进程的标准输出流(到父进程中就是输入流了,对方输出我接受,那么到这里就变成我的输入流了)
ii. InputStream Process.getErrorStream(); // 获得子进程的标准错误流(到父进程中就是输入流了);
iii. OutputStream Process.getOutputStream(); // 获得子进程的标准输入流(在父进程中就是输出流,父进程朝子进程输出,到了子进程就是子进程的输入流了)
!!规律:
a. getInputStream和getOutputStream都是字面意义,同时也是站在父进程角度的,即getInputStream得到的就是输入流,getOutputStream得到的就是输出流;
b. 因此无需死记硬背,输入流就是输入,那必定是对方的输出流,而输出流就是输出,必定到对面就是输入流了,只不过默认绑定的都是对方的标准流;
c. 只有getErrorStream比较特殊,它得到的是对方的错误流,对方的错误流是输出流,那么到了父进程就是输入流了(从返回值可以看出)
4) 示例:getErrorStream的应用(getInputStream和getErrorStream其实是一样的,都是获取子进程的输出)
1) 标准I/O流就是指System.in、System.out、System.err这三个,分表表示标准输入流、标准输出来、标准错误流;
2) 三者默认的流节点分别是键盘、屏幕、屏幕,这也是我们频繁使用的三个I/O流;
2. 标准流重定向:
1) 即人为改变三个标准流的流节点,比如吧System.out的流节点人为改成某个文件,那么在使用System.out输出的时候就不是输出到屏幕了而是输出到那个文件了;
2) 简单地说就是改变标准流原来默认的流向而已;
3) System提供了3个静态方法对标准流重定向:
i. static void setIn(InputStream in); // 重定向标准输入流
ii. static void setOut(PrintStream out); // 重定向标准输出流
iii. static void setErr(PrintStream err); // 重定向标准错误流
!!可以看到两个输出流必须要用处理流来重定向(当然必须要确定底层的流节点),而输入流一般用一个节点流来重定向就行了;
4) 示例:分别重定向输出流和输入流
public class Test { public static void main(String[] args) throws IOException { try (PrintStream ps = new PrintStream(new FileOutputStream("out.txt"))) { PrintStream old = new PrintStream(System.out); // 备份 System.setOut(ps); System.out.println("lalala"); System.out.println(new Test()); System.setOut(old); // 还原 } try (FileInputStream fis = new FileInputStream("src\\com\\lirx\\Test.java")) { System.setIn(fis); Scanner sc = new Scanner(System.in); sc.useDelimiter("\n"); while (sc.hasNext()) { System.out.println(sc.next()); } } } }
3. JVM读写其它进程的数据:
1) 我们知道可以通过Runtime.getRuntime().exec(String cmd)在当前进程中执行平台上的另一个子进程,该方法返回代表该子进程句柄的Process对象;
2) 现在我们要做的就是父子两个进程之间进行通信(数据交流);
3) Process对象提供了三个方法来达到上述目的:三个方法均以当前进程(即父进程)为视角出发的
i. InputStream Process.getInputStream(); // 获得子进程的标准输出流(到父进程中就是输入流了,对方输出我接受,那么到这里就变成我的输入流了)
ii. InputStream Process.getErrorStream(); // 获得子进程的标准错误流(到父进程中就是输入流了);
iii. OutputStream Process.getOutputStream(); // 获得子进程的标准输入流(在父进程中就是输出流,父进程朝子进程输出,到了子进程就是子进程的输入流了)
!!规律:
a. getInputStream和getOutputStream都是字面意义,同时也是站在父进程角度的,即getInputStream得到的就是输入流,getOutputStream得到的就是输出流;
b. 因此无需死记硬背,输入流就是输入,那必定是对方的输出流,而输出流就是输出,必定到对面就是输入流了,只不过默认绑定的都是对方的标准流;
c. 只有getErrorStream比较特殊,它得到的是对方的错误流,对方的错误流是输出流,那么到了父进程就是输入流了(从返回值可以看出)
4) 示例:getErrorStream的应用(getInputStream和getErrorStream其实是一样的,都是获取子进程的输出)
public class Test { public static void main(String[] args) throws IOException { Process p = Runtime.getRuntime().exec("javac"); // 直接调用javac而不带参数是错误的,因此会触发子进程的错误流 try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()))) { String buf = null; // 打印子进程的错误提示信息(注意!是字符形式的) while ((buf = br.readLine()) != null) { System.out.println(buf); } } } }5) 示例:getOutputStream的应用
public class Test { // 父进程开启子进程,然后用自己的输出来取代子进程的标准输入 public static void main(String[] args) throws IOException { Process p = Runtime.getRuntime().exec("java ChildTest"); try (PrintStream ps = new PrintStream(p.getOutputStream())) { ps.println("123456"); // 子进程所谓的“键盘输入”其实是这两句内容 ps.println("lalalala"); } } } class ChildTest { // 子进程从键盘读入然后打印到文件 public static void main(String[] args) throws Exception { try ( Scanner sc = new Scanner(System.in); PrintStream ps = new PrintStream(new FileOutputStream("test.out")) ) { sc.useDelimiter("\n"); while (sc.hasNext()) { ps.println("keyboard input: " + sc.next()); } } } }
相关文章推荐
- Java的泛型类
- springMVC的生命周期
- ssm整合说明与模板-Spring Spring MVC Mybatis整合开发
- ssm整合说明与模板-Spring Spring MVC Mybatis整合开发
- Java多线程中的interrupt方法的使用
- java内存回收机制
- HashMap源码注解 之 put()方法(六)
- springMVC(2)------springMVC配置实例(注解)
- [翻译]Java Garbage Collection Basics Java 垃圾回收基础 之2 Java 技术与JVM
- Maven+Spring+mybatis项目搭建
- java-一维数组的随机赋值
- JAVA 如何使用 MD5 和SHA1进行数据加密
- [翻译]Java Garbage Collection Basics Java 垃圾回收基础 之1 概览
- Java中的volatile关键字
- java-一维数据的应用
- [翻译]Java Garbage Collection Basics Java 垃圾回收基础 目录
- 我是一个Java class
- 用java开发编译器之Thompson构造:正则表达式的词法解析
- Java Collection API中的表
- myeclipse快捷键集合