Java IO 之 FilterInputStream/FilterOutputStream

来源:互联网 发布:手机摄像头驱动软件 编辑:程序博客网 时间:2024/05/06 23:34

前面两篇介绍了许多输入输出类,但可以看出每个类的功能都比较单一。若想将各种功能组合使用,就需要装饰器模式。

FilterInputStream和FilterOutputStream也是由InputStream和OutputStream派生而来,这也是装饰器模式的要求(装饰器必须具有和它所装饰的对象相同的接口)。

Java 1.6中被Filter类装饰的有:

BufferedInputStream/BufferedOutputStreamDataInputStream/DataOutputStreamLineNumberInputStreamPushbackInputStreamPrintStream

下图是以BufferedInputStream为例的继承结构图,由图可以看出上述5个类与FilterInputStream/FilterOutputStream、InputStream/OutputStream之间的关系:
这里写图片描述

接下来,我们首先以FilterInputStream为例,看看其与InputStream有何区别:
FilterInputStream 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据也可以提供一些额外的功能。这点可以从其构造函数看出:

FilterInputStream(InputStream in)

类FilterInputStream本身也只是重写将请求传递给in的方法,提供额外的功能,其子类也可以进一步重写这些方法。

FilterInputStream的方法摘要:

方法          解释available()  返回下一次可以从输入流读取或者跳过的字节数。close()      关闭输入流并释放相关资源。mark(int)    对输入流的当前位置作标记。markSupported() 测试输入流是否支持markreset方法。read()       从输入流中读取下一个数据字节。read(byte[]) 从输入流读取若个字节放入参数的字节数组中,读取的字节个数为数组的长度。read(byte[],int,int) 从输入流中读取指定字节放入参数的字节数组中。reset()      将输入流重新定位到最后一次mark标记的位置。skip(long)   跳过且丢弃输入流中的若干字节,个数有参数指定。

看起来,好像FilterInputStream的方法与InputStream中的方法没什么不同。但FilterInputStream的子类却给出了更多的实现。例子中不过多剖析源码,主要讲述其子类的特殊点。

代码实例:
1 BufferedInputStream
该类最大的特点是使用了缓冲区,与不使用缓冲区的区别在于:使用缓冲区的时候,无论读取还是写入都会更快。因为不使用缓冲区的时候,每读取一个字节就会写入一个字节,但是涉及磁盘的IO操作效率很慢,所以这种方式效率很慢。若使用了缓冲区,可以一次性读取多个字节放在缓冲区中,等到缓冲区满,再一次性写入磁盘。可见使用缓冲区的时候可以有效减少磁盘IO操作次数,效率可以提高很多。

/* testBuffered.txt是一个大小在6000KB左右的文件,分别采用FileInputStream(未经FilterInputStream修饰了的)和BufferedInputStream读取(经FilterInputStream修饰了的)*/    public void testFile() {        File f=new File("testBuffered.txt");        FileInputStream in=new FileInputStream(f);        int flag=0;        Date d1=new Date();        while (flag!=-1){            flag=in.read();        }        Date  d2=new Date();        System.out.println(d2.getTime()-d1.getTime());/*Output:7856*/      public void testBuffered() {        File f=new File("testBuffered.txt");        InputStream in=new FileInputStream(f);        BufferedInputStream bin=new BufferedInputStream(in);        int flag=0;        Date d1=new Date();        while (flag!=-1){            flag=bin.read();        }        Date  d2=new Date();        System.out.println(d2.getTime()-d1.getTime());    }   /*167*/          }

可以看出,BufferedInputStream的效率比FileOutputStream效率快很多。所以,在读取大文件的时候,BufferedInputStream具有一定的优势。

2 DataInputStream
该类允许从底层输入流中读取Java基本数据类型,当你需要输入输出流与平台无关时,可以选择该类。

public void testData() throws IOException{        File f=new File("testData.txt");        OutputStream out=new FileOutputStream(f);        DataOutputStream dout=new DataOutputStream(out);        /* 本例子尝试了Int和char型,实验中可以发现文本testData.txt中存储的并不一定是我们想要存储的(因为这个跟机器有关),但读出的一定是我们想要的*/        //dout.writeInt(100);        dout.writeChar('u');        InputStream in=new FileInputStream(f);        DataInputStream din=new DataInputStream(in);        try {            char c;            int i;            while(true){                c=din.readChar();                //i=din.readInt();                System.out.println(c);                //System.out.println(i);            }        } catch (EOFException e) {            // TODO: handle exception        }    }/*Output:100  和  u*/

3 LineNumberInputStream

该类的特点是它提供了跟踪当前行号的附加功能。

    public void testLine() {        File f=new File("testLine.txt");        InputStream in=new FileInputStream(f);        LineNumberInputStream lin=new LineNumberInputStream(in);        System.out.println("Now the line number is: "+lin.getLineNumber());        lin.read();        System.out.println("Now the line number is: "+lin.getLineNumber());        lin.setLineNumber(3);        System.out.println("Now the line number is: "+lin.getLineNumber());    }/*testLine.txt:100100100100100Output:Now the line number is: 0Now the line number is: 0Now the line number is: 3*/

目前该类已经被废弃了。

4 PushbackInputStream
该类的特点是增加了“推回”(push back) 或者叫“取消读取”(unread)一个字节的能力。

public void testPush() {        byte[] buf={12,45,78,54,87,22};        ByteArrayInputStream in=new ByteArrayInputStream(buf);        PushbackInputStream pin=new PushbackInputStream(in);        int first=pin.read();        System.out.println("The first is: "+first);        System.out.println("The next byte is: "+pin.read());        /*unread(int)方法推回一个字节,将其复制到推回缓冲区之前。此方法调用后,要读取的下一个字节的值为参数。        */        pin.unread(first);        System.out.println("Now the next byte is: "+pin.read());    }/*Output:The first is: 12The next byte is: 45Now the next byte is: 12*/

5 PrintStream
PrintStream是我们最经常使用的类,print()、println()等都是该类的方法。该类可以方便的打印各种数据值表示形式。

0 0
原创粉丝点击