java标准流重定向和管道 - cyclonefly0000的专栏 - 博客频道 - CSDN.NET
java标准流重定向和管道
前几天用到了管道流,在使用的过程中又涉及到了流的重定向,在这里总结一下,还有一些问题不太明白,希望网友能点评一下。
网上说的重定向主要是LINUX里边,也有java标准流的重定向。都是把一个输入流定向到另一个输出流(个人感是输出流定向到另一个输入流,相对来说)。
下边的例子就是把程序的输出流重定向到一个文件(流)中。
- import java.io.*;
- public class Redirect {
- public static void main(String[] args) throws IOException {
- File f=new File("out.txt");
- f.createNewFile();
- System.out.println("这句从控制台输出,不会输出到文件out.txt");
- FileOutputStream fileOutputStream = new FileOutputStream(f);
- PrintStream printStream = new PrintStream(fileOutputStream);
- System.setOut(printStream);
- System.out.println("默认输出到控制台的这一句,输出到了文件 out.txt");
- }
- }
下面是从网上找的一个例子。是把程序的输出内容重定向到GUI组件中。
- import java.io.OutputStream;
- import java.io.PrintStream;
- import javax.swing.SwingUtilities;
- import javax.swing.text.JTextComponent;
- public class GUIPrintStream extends PrintStream {
- private JTextComponent component;
- private StringBuffer sb = new StringBuffer();
- public GUIPrintStream(OutputStream out, JTextComponent component) {
- super(out);
- this.component = component;
- }
- @Override
- public void write(byte[] buf, int off, int len) {
- final String message = new String(buf, off, len);
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- sb.append(message);
- component.setText(sb.toString());
- }
- });
- }
- }
- public class MainFrame extends javax.swing.JFrame {
- private javax.swing.JButton btnOut;
- private javax.swing.JScrollPane scrollPane;
- private javax.swing.JTextArea textArea;
- public MainFrame() {
- initComponents();
- // 重定向到通过文本组件构建的组件输出流中。
- System.setOut(new GUIPrintStream(System.out, textArea));
- }
- private void initComponents() {
- scrollPane = new javax.swing.JScrollPane();
- textArea = new javax.swing.JTextArea();
- btnOut = new javax.swing.JButton();
- setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
- setTitle("标准输出重定向到GUI - www.chenwei.mobi");
- textArea.setColumns(20);
- textArea.setRows(5);
- scrollPane.setViewportView(textArea);
- getContentPane().add(scrollPane, java.awt.BorderLayout.CENTER);
- btnOut.setText("System.out.println(System.getProperties());");
- btnOut.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- btnOutActionPerformed(evt);
- }
- });
- getContentPane().add(btnOut, java.awt.BorderLayout.PAGE_END);
- pack();
- }
- private void btnOutActionPerformed(java.awt.event.ActionEvent evt) {
- System.out.println(System.getProperties());
- }
- public static void main(String args[]) {
- java.awt.EventQueue.invokeLater(new Runnable() {
- public void run() {
- new MainFrame().setVisible(true);
- }
- });
- }
- }
这个例子相对上一个较复杂点儿,认真看一下也不难,就是把程序本应该输出到控制台的内容重定向到JTEXT里显示。看完这两个例子,发觉重定向只是针对程序输出的内容(在JAVA里也就是System.out.println()的内容,当然还有System.err),如果把程序输出内容换成其们流比如,本来是把System.out.println("......")的内容定向到out.txt里,我现在有一个文件叫in.txt。我把他“重定向”到out.txt .大家这时就会觉得是什么样的呢?就是把一个流的传递。把in.txt当做out.txt的“参数”传给他。
个人感觉标流的重定向就是叫法上的不一样。大家有什么想法也说说。
下面我们看一下管道流,感觉里边渗杂着流的重定向。
- import java.io.IOException;
- import java.io.PipedInputStream;
- import java.io.PipedOutputStream;
- class Send implements Runnable {
- // 实现Runnable接口
- private PipedOutputStream pos = null; // 管道输出流
- public Send() {
- this.pos = new PipedOutputStream();// 实例化输出流
- }
- public void run() {
- String str = "Hello";
- try {
- this.pos.write(str.getBytes()); // 输出信息
- } catch (IOException e) {
- e.printStackTrace();
- }
- try {
- this.pos.close(); // 关闭输出流
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public PipedOutputStream getPos() { // 通过线程类得到输出流
- return pos;
- }
- }
- class Receive implements Runnable { // 实现Runnable接口
- private PipedInputStream pis = null;
- public Receive() {
- this.pis = new PipedInputStream(); // 实例化输入流
- }
- public void run() {
- byte b[] = new byte[1024];
- int len = 0;
- try {
- len = this.pis.read(b); // 接收数据
- } catch (IOException e) {
- e.printStackTrace();
- }
- System.out.println("接收的内容为:" + new String(b, 0, len));
- try {
- this.pis.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public PipedInputStream getPis() {
- return pis;
- }
- }
- public class PipedDemo1 {
- public static void main(String[] args) {
- Send s = new Send();
- Receive r = new Receive();
- try {
- s.getPos().connect(r.getPis()); // 连接管道
- } catch (IOException e) {
- e.printStackTrace();
- }
- new Thread(s).start(); // 启动线程
- new Thread(r).start(); // 启动线程
- }
这是一个简单的管道流的应用。是不是也是一个流的重定向(个人觉得是)。
下面这个例子是我在写程序时遇到的。
- import java.io.BufferedReader;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.ArrayList;
- public class Test {
- /**
- * discripe
- * parameter
- * @param args
- */
- public static void main(String[] args) throws Exception{
- Runtime rt=Runtime.getRuntime();
- Process process1=rt.exec("ps -aux");
- Process process2=rt.exec("grep "+"root");
- // Process process3=rt.exec("ps -aux|grep root");
- InputStream is=null;
- InputStreamReader isr=null;
- BufferedReader buffer=null;
- String line=null;
- ArrayList<String> list=new ArrayList<String>();
- // System.out.println("-------------------------------------------------------------");
- // InputStream is1 = process1.getInputStream();
- // isr=new InputStreamReader(is1);
- // buffer=new BufferedReader(isr);
- // while((line=buffer.readLine())!=null){
- // System.out.println(line);
- // list.add(line);
- // }
- //
- // System.out.println("-------------------------------------------------------------");
- //
- // InputStream is2 = process2.getInputStream();
- // isr=new InputStreamReader(is2);
- // buffer=new BufferedReader(isr);
- // while((line=buffer.readLine())!=null){
- // System.out.println(line);
- // list.add(line);
- // }
- // System.out.println("-------------------------------------------------------------");
- is = Piper.pipe(process1,process2);
- isr=new InputStreamReader(is);
- buffer=new BufferedReader(isr);
- while((line=buffer.readLine())!=null){
- System.out.println(line);
- list.add(line);
- }
- process1.destroy();
- process2.destroy();
- }
- }
- import java.io.InputStream;
- import java.io.OutputStream;
- public class Piper implements java.lang.Runnable {
- private InputStream input;
- private OutputStream output;
- public Piper(InputStream input, OutputStream output) {
- this.input = input;
- this.output = output;
- }
- public void run() {
- try {
- // Create 512 bytes buffer
- byte[] b = new byte[512];
- int read = 1;
- // As long as data is read; -1 means EOF
- while (read > -1) {
- // Read bytes into buffer
- read = input.read(b, 0, b.length);
- //System.out.println("read: " + new String(b));
- if (read > -1) {
- // Write bytes to output
- output.write(b, 0, read);
- }
- }
- } catch (Exception e) {
- // Something happened while reading or writing streams; pipe is broken
- throw new RuntimeException("Broken process", e);
- } finally {
- try {
- input.close();
- } catch (Exception e) {
- }
- try {
- output.close();
- } catch (Exception e) {
- }
- }
- }
- public static InputStream pipe(Process... proc) throws InterruptedException {
- // Start Piper between all processes
- Process p1;
- Process p2;
- for (int i = 0; i < proc.length; i++) {
- p1 = proc[i];
- // If there's one more process
- if (i + 1 < proc.length) {
- p2 = proc[i + 1];
- // Start piper
- new Thread(new Piper(p1.getInputStream(), p2.getOutputStream())).start();
- }
- }
- Process last = proc[proc.length - 1];
- // Wait for last process in chain; may throw InterruptedException
- last.waitFor();
- // Return its InputStream
- return last.getInputStream();
- }
- }
上面的这个例子如果直接用
- Process process3=rt.exec("ps -aux|grep root");是会出错的,后来一往网友说<a href="http://www.iteye.com/problems/69965" target="_blank">点击打开链接</a>如是。这个是我临时在那个社区里发的。
- 其实还是搞不明白process1的结果怎么传给process2,我不是说上边Piper类。在linux里ps -aux|grep root这句话是一个什么的执行机制。知道的网友说一下。不要说比如“ps -aux的结果传给grep root”这类的话,太笼统了,不明白。