A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 明锦添 中级黑马   /  2013-4-25 19:52  /  1133 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

管道流有什么用?它能将一个文件中的内容通过循环读写的方式复制到另一个文件中吗?它们循环读写的时候是怎么对接的?毕老师的视频里完全没有介绍求解释

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

3 个回复

正序浏览
如果仍有问题,请继续追问,如果问题已解决,请将分类改为已解决,谢谢
回复 使用道具 举报
本帖最后由 HM朱蛟 于 2013-4-25 23:12 编辑

这个问题我觉得要是要接触了实际项目才能有深切的体会。
不过这需要一个过程,我看这个视频的时候也不是很明白,纠结半天,但是调整了下心态,就像毕老师说的:“有些问题我们不需要理解的那么深”,确实,有些问题我们花费太多精力反而是事倍功半,姑且先学会“如何使用”。听之任之,存疑信之。今后在使用过程中再慢慢巩固。(针对一些短时间无法掌握牢固的知识点)

我学习这里的时候做过一些总结,不求完全解惑,但求对楼主有所用处吧。


管道流
涉及到了多线程的IO技术

一个线程读,一个线程写
2个管道即使你一个线程执行时,遇见阻塞式方法都不用怕。你这个线程挂了,CPU会执行你另一个线程。互相不影响
------------------------------------------------------------------------

Java I/O系统是建立在数据流概念之上的,
而在UNIX/Linux中有一个类似的概念,
就是管道,
它具有将一个程序的输出当作另一个程序的输入的能力。
在Java中,
可以使用管道流进行线程之间的通信,
输入流和输出流必须相连接,
这样的通信有别于一般的共享数据通信,
其不需要一个共享的数据空间。

------------------------------------------------------------------------

管道流的读写方法都是阻塞式的,所以:
如果写入线程完成了写入操作,当读取流读取数据之前此线程会阻塞,所以此时只有读取流能够获得资源执行
读取流同上
所以他们会很协调的运行

------------------------------------------------------------------------

一个概念上的问题。IO流只有一种表现形态,即要么输出,要么输入。
这样就有了InputStream和OutputStream。再说一点,
流是可以相互包含的,即输入流可以接受输出对象,输出流可以接受输入对象

------------------------------------------------------------------------

Demo:

  1. import java.io.*;
  2. class Run
  3. {
  4.         //main
  5.         public static void main(String [] args)throws Exception
  6.         {
  7.           PipedInputStream in = new PipedInputStream();//创建管道流
  8.           PipedOutputStream out = new PipedOutputStream();//创建管道流

  9.           in.connect(out); //接上

  10.           Read r = new Read(in);
  11.           Write w = new Write(out);
  12.          
  13.                 new Thread(r).start();
  14.                 new Thread(w).start();
  15.                
  16.         }
  17.         
  18.         public static void sop(Object obj)
  19.         {
  20.                 System.out.println(obj);
  21.         }        
  22. }

  23. //1:建立2个Runnable接口
  24. class Read implements Runnable//读
  25. {
  26.         private PipedInputStream in ;
  27.         
  28.         //2 构造函数接收进来一个管道流,这里是读取流
  29.         Read(PipedInputStream in)
  30.         {
  31.                         this.in = in ;
  32.         }

  33.         //多线程,复写run方法
  34.         public void run()
  35.         {
  36.                 try //不能抛异常。
  37.                 {

  38.                         byte[] buf = new byte[1024];//读数据容器
  39.                         
  40.                   System.out.println("读取前,没有数据,阻塞");
  41.                                                                   
  42.                         int len =(in.read(buf));//往数组里面读。
  43.                                                 //PipedInputStream也是InputStream的子类,所以这里调用的是父类的Read方法
  44.                         
  45.                         String s = new String(buf,0,len);
  46.                         
  47.                         System.out.println(s);//打印
  48.                         
  49.                         in.close();//关闭
  50.                 }
  51.                
  52.                 catch (IOException e)
  53.                 {
  54.                          throw new RuntimeException("管道读取流失败");
  55.                 }
  56.         }
  57. }


  58. class Write implements Runnable//写
  59. {
  60.         private PipedOutputStream out ;
  61.         //2 构造函数接收进来一个管道流,这里是读取流
  62.         Write(PipedOutputStream out)
  63.         {
  64.                         this.out = out ;
  65.         }

  66.         //多线程,复写run方法
  67.         public void run()
  68.         {
  69.                 try
  70.                 {
  71.                         System.out.println("等待6秒写入");
  72.                         Thread.sleep(6000);//我让他停6秒
  73.                         out.write("piped lai la".getBytes());//写入字节流
  74.                         out.close();        //关流
  75.                 }
  76.                 catch (Exception e)
  77.                 {
  78.                           throw new RuntimeException("管道输出流失败");
  79.                 }
  80.         }
  81. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 很给力!

查看全部评分

回复 使用道具 举报
管道流的主要作用是可以进行两个线程之间的通信,分为管道输出流和管道输入流,如果想要进行管道输出,则必须把输出流连在输入流之上。用管道流进行读写操作需要将读与写分开到不同的线程,这样不会发生线程阻塞的问题。例如:
import java.io.*;
public class Listing {
    static PipedInputStream pipedIS = new PipedInputStream();
    static PipedOutputStream pipedOS = new PipedOutputStream();
    public static void main(String[] args) {
        try {
            pipedIS.connect(pipedOS);
        }
        catch(IOException e) {
            System.err.println("连接失败");
            System.exit(1);
        }
        byte[] inArray = new byte[10];
        int bytesRead = 0;
        startWriterThread();   // 启动写操作线程
        try {
            bytesRead = pipedIS.read(inArray, 0, 10);
            while(bytesRead != -1) {
                System.out.println("已经读取" + bytesRead + "字节...");
                bytesRead = pipedIS.read(inArray, 0, 10);
            }
        }
        catch(IOException e) {
            System.err.println("读取输入错误.");
            System.exit(1);
        }
    }
    // 创建一个独立的线程执行写入PipedOutputStream的操作
    private static void startWriterThread() {
        new Thread(new Runnable() {
            public void run() {
                byte[] outArray = new byte[2000];
                while(true) { // 无终止条件的循环
                    try {
                        // 在该线程阻塞之前,有最多1024字节的数据被写入
                        pipedOS.write(outArray, 0, 2000);
                    }
                    catch(IOException e) {
                        System.err.println("写操作错误");
                        System.exit(1);
                    }
                    System.out.println("     已经发送2000字节...");
                }
            }
        }).start();
    }
}

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马