黑马程序员_JAVA之IO流

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

      Java 的IO 流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作, Java 中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为"流" (stream) ,通过流的方式允许Java 程序使用相同的方式来访问不同的输入/输出源。stream 是从起源(source) 到接收(sink) 的有序数据。

      流按照相对于内存的方向分为输入流和输出流,也可以按照读写的单位分为字节流和字符流,而且还可以根据流的使用不同分为节点流和封装流(采用了典型的装饰器的设计模式,使得IO流用起来非常灵活)。


以下是字节流和字符流的层次图。

 
黑马程序员_JAVA之IO流_第1张图片

由上图可看出,java IO 体系中有访问文件,数组,管道和字符串的节点流;以及缓冲流,对象流,推回输入流,特殊流

等高层处理流;还有两个转换流。

 下面程序分别使用了字节和字符读取文件并复制一份,并且与buffered版本进行了对比。

package stream;  
  
import java.io.BufferedInputStream;  
import java.io.BufferedOutputStream;  
import java.io.BufferedReader;  
import java.io.BufferedWriter;  
import java.io.FileInputStream;  
import java.io.FileOutputStream;  
import java.io.FileReader;  
import java.io.FileWriter;  
import java.io.IOException;  
import java.io.Writer;  
  
public class Streamtest {  
  
    /** 
     * @param args 
     * @throws IOException 
     */  
    public static void main(String[] args) throws IOException {  
        FileInputStream fileInputStream = null;  
        FileOutputStream fileOutputStream = null;  
        FileReader fReader = null;  
        FileWriter fWriter = null;  
        BufferedInputStream bis = null;  
        BufferedOutputStream bos = null;  
        BufferedReader br=null;  
        BufferedWriter bw=null;  
          
        //stream  
        long byteStart =System.currentTimeMillis();  
        try {  
              
            fileInputStream = new FileInputStream("三国演义.txt");  
            fileOutputStream = new FileOutputStream("三国演义副本一.txt");  
            int hasRead = 0;  
            byte[] buf = new byte[10];  
            while ((hasRead = fileInputStream.read(buf)) > 0) {  
                fileOutputStream.write(buf, 0, hasRead);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (fileInputStream != null)  
                fileInputStream.close();  
            if (fileOutputStream != null)  
                fileOutputStream.close();  
            long byteEnd=System.currentTimeMillis();  
            System.out.println("字节复制完毕!花费"+(byteEnd-byteStart)+" ms.");  
        }  
        //buffered stream  
        long bufferedByteStart =System.currentTimeMillis();  
        try {  
              
            fileInputStream = new FileInputStream("三国演义.txt");  
            fileOutputStream = new FileOutputStream("buffered三国演义副本一.txt");  
            bis=new BufferedInputStream(fileInputStream);  
            bos=new BufferedOutputStream(fileOutputStream);  
            int hasRead = 0;  
            byte[] buf = new byte[10];  
            while ((hasRead = bis.read(buf)) > 0) {  
                bos.write(buf, 0, hasRead);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (bis != null)  
                bis.close();  
            if (bos != null)  
                bos.close();  
            long bufferedByteEnd=System.currentTimeMillis();  
            System.out.println("buffered字节复制完毕!花费"+(bufferedByteEnd-bufferedByteStart)+" ms.");  
        }  
          
              
        //reader writer  
        long charStart=System.currentTimeMillis();  
        try {  
            fReader = new FileReader("三国演义.txt");  
            fWriter = new FileWriter("三国演义副本二.txt");  
            char[] cbuf = new char[10];  
            int hasRead = 0;  
            while ((hasRead = fReader.read(cbuf)) > 0) {  
                fWriter.write(cbuf, 0, hasRead);  
            }  
  
        } catch (IOException e) {  
            // TODO: handle exception  
        } finally {  
            if (fReader != null)  
                fReader.close();  
            if (fWriter != null)  
                fWriter.close();  
            long charEnd=System.currentTimeMillis();  
            System.out.println("字符复制完毕! 花费"+(charEnd-charStart)+" ms.");  
        }  
          
        //buffered reader writer   
        long bufferedCharStart=System.currentTimeMillis();  
        try {  
            fReader = new FileReader("三国演义.txt");  
            fWriter = new FileWriter("buffered三国演义副本二.txt");  
            br=new BufferedReader(fReader);  
            bw=new BufferedWriter(fWriter);  
            char[] cbuf = new char[10];  
            int hasRead = 0;  
            while ((hasRead = br.read(cbuf)) > 0) {  
                bw.write(cbuf, 0, hasRead);  
            }  
  
        } catch (IOException e) {  
            // TODO: handle exception  
        } finally {  
            if (br != null)  
                br.close();  
            if (bw != null)  
                bw.close();  
            long bufferedCharEnd=System.currentTimeMillis();  
            System.out.println("buffered字符复制完毕!花费"+(bufferedCharEnd-bufferedCharStart)+" ms.");  
        }  
  
    }  
  
}

结果可以看出,buffered封装后却是提高了效率。

  1. 字节复制完毕!花费1020 ms.  

  2. buffered字节复制完毕!花费21 ms.  

  3. 字符复制完毕! 花费90 ms.  

  4. buffered字符复制完毕!花费30 ms.  

关于buffer:首先要知道什么是缓冲,buffering,如CPU和硬盘之间的关系,寄存器或内存就是作为缓冲,如果没有缓冲,当CPU要向硬盘存取数据时,只能直接存取,导致效率低下。
比如总共要读取10个字符,每次用一个,那只能每次从硬盘读一个用一个,如果有缓冲,就能先直接缓冲10个,然后再从缓冲中读一个用一个,出于硬件条件等的天生受限,使用buffering会大大提高效率。

 

PrintStream 和 PrintWriter

 

PrintStream是OutputStream的子类,PrintWriter是Writer的子类,两者处于对等的位置上,所以它们的API是非常相似的。PrintWriter实现了PritnStream的所有print方法。对于PrintStream,所有println方法都在内部调用相应的print方法,比如println(char x)的方法体就是调用print(x);再写入一个平台相关的换行符。PrintStream构建时会在内部new一个BufferedWriter,所有print方法都在内部调用这个Writer的write方法(write(String)或write(char[]))——对于print(char[]),直接调用write(char[]);对于其他的print方法,先用String.valueOf获得参数的字符串表示,然后调用write(String)。
         对于PrintWriter,所有println方法也都在内部调用print方法,print方法调用write方法。传入OutputStream时,PrintWriter会在内部构造一个BufferedWriter;而传入Writer时,PrintStream内部直接使用该Writer,此时PrintWriter是否进行了缓冲全看该Writer。
所以,对于使用print系列方法的场合,二者没什么区别。

         但是,PrintStream是字节流,它有处理raw byte的方法,write(int)和write(byte[],int,int);PrintWriter是字符流,它没有处理raw byte的方法。PrintStream和PrintWriter的auto flushing机制有点不同,前者在输出byte数组、调用println方法、输出换行符或者byte值10(即\n)时自动调用flush方法,后者仅在调用println方法时发生auto flushing。


你可能感兴趣的:(黑马程序员_JAVA之IO流)