zoukankan      html  css  js  c++  java
  • Java中InputStream装饰器模式的大家族

    你好!欢迎阅读我的博文,你可以跳转到我的个人博客网站,会有更好的排版效果和功能。
    此外,本篇博文为本人Pushy原创,如需转载请注明出处:https://pushy.site/posts/1519819757

    本文写在po主初学JAVA时,在学习inputStream摸不着头脑,受Java IO-InputStream家族 -装饰者模式一文启发,所以在理清思路时写下本文。因为初学,如有错误,望指正。

    因为和输入流与之对应的还有输出流(即OutputStream),在此只针对输入流InputStream讨论。

    1. 家族老大:

    一说起家族中的老大,InputStream自然是当仁不让,在java的输入流操作的类中,衍生出的基本子类有,可以理解为这些都是InputStream它的孩子(子类):

    InputStream作为所有输入流中的超类,包含从输入流读取数据的基本方法,所有的具体类都包含了这些方法,例如read()方法,它将读取一个字节并将其以int类型返回,当到达输入流的结尾时,返回-1,因此我们常常这样操作:

    byte data;
    while ((data = (byte) bis.read()) != -1) {
    	// 当没有达到输入流的结尾时,继续读取并打印转换成char类型的字符:
        System.out.print((char) data);
    }
    

    这段代码不了解不要紧,现在我们开始正式介绍InputStream家族。

    2. 家族孩子:

    家族中的子类各司其职,老大FileInputStream处理文件流,老二ByteArrayInputStream处理字节数组流...

    例如,我们来看下老大是怎么工作的:

    import java.io.*;
    import java.util.Date;
    
    public class FileInputStreamTest {
        public static void main(String[] args) throws Exception{
            try {
            	// 创建FileInputStream对象:
    			FileInputStream fis = new FileInputStream("E:\text.txt");
                // 得到起始时间:
                long start = System.currentTimeMillis( );
                byte byteData;
                while ((byteData = (byte) bis.read()) != -1) {
                    System.out.print((char) byteData);
                }
                // 得到读取后的结束时间:
                long end = System.currentTimeMillis( );
                // 计算出读取的时间:
                long diff = end - start;
                System.out.println("读取的时间时间共:" +  diff);
                fis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    工作完成后,我们可以得到老大干完活的花费的时间为:1097,但是家族老大嫌这家伙干活太慢了。老大无奈,叫来了它的弟弟老二BufferedInputStream,俗话说啊,兄弟齐心,其利断金。果不其然,兄弟俩一块干活效率果然加快了不少:

    在如下的代码中我们可以看到,通过将FileInputStream放到BufferedInputStream中的构造方法中去创建BufferedInputStream对象,这样FileInputStream也就具有了缓存的输入流功能。

    public class BufInputStream {
        public static void main(String[] args) throws Exception{
            try {
                // 通过缓冲区数据向输入流添加功能,维护一个内部缓冲区以存储从底层输入流读取的字节:
    			BufferedInputStream bis  = new BufferedInputStream(new FileInputStream("E:\text.txt"));
                long start = System.currentTimeMillis( );
                byte byteData;
                while ((byteData = (byte) fis.read()) != -1) {
                    System.out.print((char) byteData);
                }
                long end = System.currentTimeMillis( );
                long diff = end - start;
                System.out.println("读取的时间时间共:" +  diff);
                bis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    

    现在我们来看下兄弟俩一块工作花费的时间吧:281。嘿!果然快了不少!看来增加缓冲流的功能的效果的确十分明显。

    这下老二在家族的名声增大了不少,许多的兄弟都找他搭档干活了。

    3. 总结:

    通过上文的假设,我们可以明白了在io-InputStream的家族中,采用了装饰者的设计模式,即不改变原类文件和使用继承的前提下,动态地扩展一个对象的功能(比如说这里的支持缓冲流),通过创建一个包装对象(这里的BufferedInputStream),也就是装饰包裹真实的对象。

    例如我们还可以也ByteArrayInputStream中修饰PushbackInputStream类:

    PushbackInputStream  pbi = new PushbackInputStream (new ByteArrayInputStream(b));
    

    ByteArrayInputStream是处理字节数组流;PushbackInputStream是向输入流中添加功能,允许使用unread()方法推回读取的字节。这样我们就可以使用pbi对象处理字节数组,还具有推回读取字节的功能了:

    import java.io.*;
    
    public class BAStreamAndPBStream {
        public static void main(String[] args) throws IOException{
            byte[] b = {1,2,3};
            PushbackInputStream  pbi = new PushbackInputStream (new ByteArrayInputStream(b));
            int result;
            while ((result = pbi.read()) != -1) {
                System.out.print(result + " ");
                pbi.unread(result);
                pbi.read();
                System.out.print(result + " ");
            }
            pbi.close();
        }
    }
    
    // 运行结果为:
    // 1 1 2 2 3 3 
    

    好了,有关InputStream的大家族到这里介绍完了!如果你还有不明白的,可以阅读一下文章Java IO-InputStream家族 -装饰者模式

  • 相关阅读:
    CSS——制作天天生鲜主页
    HTML——制作一个图片列表
    HTML——制作一个简易菜单栏
    CSS——三种页面引入方法
    【20170903】模拟赛
    【LA 3942】 Remember the word
    【BZOJ 1036】 树的统计count
    UVA 12299 RMQ with shifts
    【20170706】次短路
    【20170706】保卫萝卜
  • 原文地址:https://www.cnblogs.com/Pushy/p/8471286.html
Copyright © 2011-2022 走看看