java标准流重定向和管道

来源:互联网 发布:手机打电话软件下载 编辑:程序博客网 时间:2024/05/03 00:52

前几天用到了管道流,在使用的过程中又涉及到了流的重定向,在这里总结一下,还有一些问题不太明白,希望网友能点评一下。


网上说的重定向主要是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;/** *//** * 输出到文本组件的流。 *  * @author Chen Wei * @website www.chenwei.mobi * @email chenweionline@hotmail.com */public class GUIPrintStream extends PrintStream {private JTextComponent component;private StringBuffer sb = new StringBuffer();public GUIPrintStream(OutputStream out, JTextComponent component) {super(out);this.component = component;}/** * 重写write()方法,将输出信息填充到GUI组件 */@Overridepublic 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");是会出错的,后来一往网友说点击打开链接如是。这个是我临时在那个社区里发的。
其实还是搞不明白process1的结果怎么传给process2,我不是说上边Piper类。在linux里ps -aux|grep root这句话是一个什么的执行机制。知道的网友说一下。不要说比如“ps -aux的结果传给grep root”这类的话,太笼统了,不明白。