java标准流重定向和管道

java标准流重定向和管道 - cyclonefly0000的专栏 - 博客频道 - CSDN.NET

java标准流重定向和管道

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

网上说的重定向主要是LINUX里边,也有java标准流的重定向。都是把一个输入流定向到另一个输出流(个人感是输出流定向到另一个输入流,相对来说)。

下边的例子就是把程序的输出流重定向到一个文件(流)中。

  1. import java.io.*;  
  2. public class Redirect {  
  3.     public static void main(String[] args) throws IOException {  
  4.   
  5.         File f=new File("out.txt");  
  6.         f.createNewFile();  
  7.         System.out.println("这句从控制台输出,不会输出到文件out.txt");  
  8.         FileOutputStream fileOutputStream = new FileOutputStream(f);  
  9.           
  10.         PrintStream printStream = new PrintStream(fileOutputStream);  
  11.         System.setOut(printStream);  
  12.         System.out.println("默认输出到控制台的这一句,输出到了文件 out.txt");  
  13.     }  
  14. }  



下面是从网上找的一个例子。是把程序的输出内容重定向到GUI组件中。

  1. import java.io.OutputStream;  
  2. import java.io.PrintStream;  
  3. import javax.swing.SwingUtilities;  
  4. import javax.swing.text.JTextComponent;  
  5.   
  6.   
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.   
  14. public class GUIPrintStream extends PrintStream {  
  15.     private JTextComponent component;  
  16.     private StringBuffer sb = new StringBuffer();  
  17.     public GUIPrintStream(OutputStream out, JTextComponent component) {  
  18.         super(out);  
  19.         this.component = component;  
  20.     }  
  21.      
  22.  
  23.   
  24.     @Override  
  25.     public void write(byte[] buf, int off, int len) {  
  26.         final String message = new String(buf, off, len);  
  27.         SwingUtilities.invokeLater(new Runnable() {  
  28.             public void run() {  
  29.                 sb.append(message);  
  30.                 component.setText(sb.toString());  
  31.             }  
  32.         });  
  33.     }  
  34. }  




  1. public class MainFrame extends javax.swing.JFrame {  
  2.     private javax.swing.JButton btnOut;  
  3.     private javax.swing.JScrollPane scrollPane;  
  4.     private javax.swing.JTextArea textArea;  
  5.     public MainFrame() {  
  6.         initComponents();  
  7.         // 重定向到通过文本组件构建的组件输出流中。  
  8.         System.setOut(new GUIPrintStream(System.out, textArea));  
  9.     }  
  10.   
  11.     private void initComponents() {  
  12.         scrollPane = new javax.swing.JScrollPane();  
  13.         textArea = new javax.swing.JTextArea();  
  14.         btnOut = new javax.swing.JButton();  
  15.         setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);  
  16.         setTitle("标准输出重定向到GUI - www.chenwei.mobi");  
  17.         textArea.setColumns(20);  
  18.         textArea.setRows(5);  
  19.         scrollPane.setViewportView(textArea);  
  20.         getContentPane().add(scrollPane, java.awt.BorderLayout.CENTER);  
  21.         btnOut.setText("System.out.println(System.getProperties());");  
  22.         btnOut.addActionListener(new java.awt.event.ActionListener() {  
  23.             public void actionPerformed(java.awt.event.ActionEvent evt) {  
  24.                 btnOutActionPerformed(evt);  
  25.             }  
  26.         });  
  27.         getContentPane().add(btnOut, java.awt.BorderLayout.PAGE_END);  
  28.         pack();  
  29.     }  
  30.   
  31.     private void btnOutActionPerformed(java.awt.event.ActionEvent evt) {  
  32.         System.out.println(System.getProperties());  
  33.     }  
  34.     public static void main(String args[]) {  
  35.         java.awt.EventQueue.invokeLater(new Runnable() {  
  36.             public void run() {  
  37.                 new MainFrame().setVisible(true);  
  38.             }  
  39.         });  
  40.     }  
  41.   
  42.   
  43. }  



这个例子相对上一个较复杂点儿,认真看一下也不难,就是把程序本应该输出到控制台的内容重定向到JTEXT里显示。

看完这两个例子,发觉重定向只是针对程序输出的内容(在JAVA里也就是System.out.println()的内容,当然还有System.err),如果把程序输出内容换成其们流比如,本来是把System.out.println("......")的内容定向到out.txt里,我现在有一个文件叫in.txt。我把他“重定向”到out.txt .大家这时就会觉得是什么样的呢?就是把一个流的传递。把in.txt当做out.txt的“参数”传给他。

个人感觉标流的重定向就是叫法上的不一样。大家有什么想法也说说。

下面我们看一下管道流,感觉里边渗杂着流的重定向。

  1. import java.io.IOException;    
  2. import java.io.PipedInputStream;    
  3. import java.io.PipedOutputStream;    
  4. class Send implements Runnable {            
  5. // 实现Runnable接口    
  6.     private PipedOutputStream pos = null;   // 管道输出流    
  7.     public Send() {    
  8.         this.pos = new PipedOutputStream();// 实例化输出流    
  9.     }    
  10.     public void run() {       
  11.           
  12.             String str = "Hello";    
  13.             try {    
  14.                 this.pos.write(str.getBytes()); // 输出信息    
  15.             } catch (IOException e) {    
  16.                 e.printStackTrace();    
  17.             }         
  18.         try {    
  19.             this.pos.close();               // 关闭输出流    
  20.         } catch (IOException e) {    
  21.             e.printStackTrace();    
  22.         }    
  23.     }    
  24.     public PipedOutputStream getPos() { // 通过线程类得到输出流    
  25.         return pos;    
  26.     }    
  27. }   
  28. class Receive implements Runnable {     // 实现Runnable接口    
  29.     private PipedInputStream pis = null;    
  30.     public Receive() {    
  31.         this.pis = new PipedInputStream();  // 实例化输入流    
  32.     }    
  33.     public void run() {           
  34.             byte b[] = new byte[1024];    
  35.             int len = 0;    
  36.             try {    
  37.                 len = this.pis.read(b);         // 接收数据    
  38.             } catch (IOException e) {    
  39.                 e.printStackTrace();    
  40.             }    
  41.             System.out.println("接收的内容为:" + new String(b, 0, len));    
  42.           
  43.         try {    
  44.             this.pis.close();    
  45.         } catch (IOException e) {    
  46.             e.printStackTrace();    
  47.         }         
  48.     }    
  49.     public PipedInputStream getPis() {    
  50.         return pis;    
  51.     }    
  52. }    
  53. public class PipedDemo1 {    
  54.     public static void main(String[] args) {    
  55.         Send s = new Send();    
  56.         Receive r = new Receive();    
  57.         try {    
  58.             s.getPos().connect(r.getPis()); // 连接管道    
  59.         } catch (IOException e) {    
  60.             e.printStackTrace();    
  61.         }    
  62.         new Thread(s).start();              // 启动线程    
  63.         new Thread(r).start();              // 启动线程    
  64.     }    

这是一个简单的管道流的应用。是不是也是一个流的重定向(个人觉得是)。

下面这个例子是我在写程序时遇到的。

  1. import java.io.BufferedReader;  
  2. import java.io.InputStream;  
  3. import java.io.InputStreamReader;  
  4. import java.util.ArrayList;  
  5.   
  6. public class Test {  
  7.   
  8.     /**  
  9.      * discripe  
  10.      * parameter   
  11.      * @param args  
  12.      */  
  13.     public static void main(String[] args) throws Exception{  
  14.         Runtime rt=Runtime.getRuntime();  
  15.         Process process1=rt.exec("ps -aux");  
  16.         Process process2=rt.exec("grep "+"root");  
  17. //      Process process3=rt.exec("ps -aux|grep root");  
  18.           
  19.         InputStream is=null;  
  20.         InputStreamReader isr=null;  
  21.         BufferedReader buffer=null;  
  22.         String line=null;  
  23.         ArrayList<String> list=new ArrayList<String>();  
  24.   
  25. //      System.out.println("-------------------------------------------------------------");          
  26. //      InputStream is1 = process1.getInputStream();  
  27. //      isr=new InputStreamReader(is1);  
  28. //      buffer=new BufferedReader(isr);  
  29. //      while((line=buffer.readLine())!=null){    
  30. //             System.out.println(line);  
  31. //          list.add(line);  
  32. //         }  
  33. //        
  34. //      System.out.println("-------------------------------------------------------------");  
  35. //                
  36. //      InputStream is2 = process2.getInputStream();  
  37. //      isr=new InputStreamReader(is2);  
  38. //      buffer=new BufferedReader(isr);  
  39. //      while((line=buffer.readLine())!=null){    
  40. //             System.out.println(line);  
  41. //          list.add(line);  
  42. //         }  
  43. //      System.out.println("-------------------------------------------------------------");  
  44.           
  45.         is = Piper.pipe(process1,process2);  
  46.         isr=new InputStreamReader(is);  
  47.         buffer=new BufferedReader(isr);  
  48.                while((line=buffer.readLine())!=null){    
  49.                    System.out.println(line);  
  50.                 list.add(line);  
  51.                }      
  52.         process1.destroy();  
  53.         process2.destroy();  
  54.     }  
  55.   
  56. }  
  1. import java.io.InputStream;  
  2. import java.io.OutputStream;  
  3. public class Piper implements java.lang.Runnable {  
  4.     private InputStream input;  
  5.     private OutputStream output;  
  6.     public Piper(InputStream input, OutputStream output) {  
  7.         this.input = input;  
  8.         this.output = output;  
  9.     }  
  10.     public void run() {  
  11.         try {  
  12.             // Create 512 bytes buffer  
  13.             byte[] b = new byte[512];  
  14.             int read = 1;  
  15.             // As long as data is read; -1 means EOF  
  16.             while (read > -1) {  
  17.                 // Read bytes into buffer  
  18.                 read = input.read(b, 0, b.length);  
  19.                 //System.out.println("read: " + new String(b));  
  20.                 if (read > -1) {  
  21.                     // Write bytes to output  
  22.                     output.write(b, 0, read);  
  23.                 }  
  24.             }  
  25.         } catch (Exception e) {  
  26.             // Something happened while reading or writing streams; pipe is broken  
  27.             throw new RuntimeException("Broken process", e);  
  28.         } finally {  
  29.             try {  
  30.                 input.close();  
  31.             } catch (Exception e) {  
  32.             }  
  33.             try {  
  34.                 output.close();  
  35.             } catch (Exception e) {  
  36.             }  
  37.         }  
  38.     }  
  39.       
  40.     public static InputStream pipe(Process... proc) throws InterruptedException {  
  41.         // Start Piper between all processes  
  42.         Process p1;  
  43.         Process p2;  
  44.         for (int i = 0; i < proc.length; i++) {  
  45.             p1 = proc[i];  
  46.             // If there's one more process  
  47.             if (i + 1 < proc.length) {  
  48.                 p2 = proc[i + 1];  
  49.                 // Start piper  
  50.                 new Thread(new Piper(p1.getInputStream(), p2.getOutputStream())).start();  
  51.             }  
  52.         }  
  53.         Process last = proc[proc.length - 1];  
  54.         // Wait for last process in chain; may throw InterruptedException  
  55.         last.waitFor();  
  56.         // Return its InputStream  
  57.         return last.getInputStream();  
  58.     }  
  59.       
  60. }  



上面的这个例子如果直接用

  1. Process process3=rt.exec("ps -aux|grep root");是会出错的,后来一往网友说<a href="http://www.iteye.com/problems/69965" target="_blank">点击打开链接</a>如是。这个是我临时在那个社区里发的。  
  1. 其实还是搞不明白process1的结果怎么传给process2,我不是说上边Piper类。在linux里ps -aux|grep root这句话是一个什么的执行机制。知道的网友说一下。不要说比如“ps -aux的结果传给grep root”这类的话,太笼统了,不明白。  
原文地址:https://www.cnblogs.com/lexus/p/2370385.html