Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例――16(二)

2014-11-24 08:05:03 · 作者: · 浏览: 2
wLine() throws IOException { write(lineSeparator); } /** * 刷新此流、同时刷新底层out流 */ public void flush() throws IOException { synchronized (lock) { flushBuffer(); out.flush(); } } /** * 关闭此流、释放与此流有关的资源。 */ public void close() throws IOException { synchronized (lock) { if (out == null) { return; } try { flushBuffer(); } finally { out.close(); out = null; cb = null; } } } }

4、实例演示:

与下面的BufferedReader结合使用实现字符类型的文件的拷贝。

二:BufferedReader


1、类功能简介:


缓冲字符输入流、他的功能是为传入的底层字符输入流提供缓冲功能、他会通过底层字符输入流(in)中的字符读取到自己的buffer中(内置缓存字符数组)、然后程序调用BufferedReader的read方法将buffer中的字符读取到程序中、当buffer中的字符被读取完之后、BufferedReader会从in中读取下一个数据块到buffer中供程序读取、直到in中数据被读取完毕、这样做的好处一是提高了读取的效率、二是减少了打开存储介质的连接次数、详细的原因下面BufferedWriter有说到。其有个关键的方法fill()就是每当buffer中数据被读取完之后从in中将数据填充到buffer中、程序从内存中读取数据的速度是从磁盘中读取的十倍!这是一个很恐怖的效率的提升、同时我们也不能无禁止的指定BufferedReader的buffer大小、毕竟、一次性读取in中耗时较长、二是内存价格相对昂贵、我们能做的就是尽量在其中找到合理点。一般也不用我们费这个心、创建BufferedReader时使用buffer的默认大小就好。


2、BufferedReader API简介:


A:构造方法


    BufferedReader(Reader in, int sz)		根据指定大小和底层字符输入流创建BufferedReader。br
    
    BufferedReader(Reader in)		使用默认大小创建底层输出流的缓冲流
 

B:一般方法


    void close()	关闭此流、释放与此流有关的所有资源
    
    void mark(int readAheadLimit)	标记此流此时的位置
    
    boolean markSupported()		判断此流是否支持标记
    
    void reset()	重置in被最后一次mark的位置
    
    boolean ready()		判断此流是否可以读取字符
    
    int read()		读取单个字符、以整数形式返回。如果读到in的结尾则返回-1。
    
    int read(char[] cbuf, int off, int len)	将in中len个字符读取到cbuf从下标off开始长度len中
    
    String readLine()	读取一行
    
    long skip(long n)		丢弃in中n个字符


3、源码分析


package com.chy.io.original.code;

import java.io.IOException;

/**
 * 为底层字符输入流添加字符缓冲cb数组。提高效率
 * @version 	1.1, 13/11/17
 * @author		andyChen
 */

public class BufferedReader extends Reader {

    private Reader in;  

    private char cb[];
    private int nChars, nextChar;

    private static final int INVALIDATED = -2;
    private static final int UNMARKED = -1;
    private int markedChar = UNMARKED;
    private int readAheadLimit = 0; /* Valid only when markedChar > 0 */

    /** If the next character is a line feed, skip it */
    private boolean skipLF = false;

    /** The skipLF flag when the mark was set */
    private boolean markedSkipLF = false;

    private static int defaultCharBufferSize = 8192;
    private static int defaultExpectedLineLength = 80;

    /**
     * 根据指定大小和底层字符输入流创建BufferedReader。br
     */
    public BufferedReader(Reader in, int sz) {
		super(in);
		if (sz <= 0)
		    throw new IllegalArgumentException("Buffer size <= 0");
		this.in = in;
		cb = new char[sz];
		nextChar = nChars = 0;
    }

    /**
     * 使用默认大小创建底层输出流的缓冲流
     */
    public BufferedReader(Reader in) {
    	this(in, defaultCharBufferSize);
    }

    /** 检测底层字符输入流in是否关闭 */
    private void ensureOpen() throws IOException {
		if (in == null)
		    throw new IOException("Stream closed");
    }

    /**
     * 填充cb。
     */
    private void fill() throws IOException {
		int dst;
		if (markedChar <= UNMARKED) {
		    /* No mark */
		    dst = 0;
		} else {
		    /* Marked */
		    int delta = nextChar - markedChar;
		    if (delta >= readAheadLimit) {
			/* Gone past read-ahead limit: Invalidate mark */
			markedChar = INVALIDATED;
			readAheadLimit = 0;
			dst = 0;
		    } else {
			if (readAheadLimit <= cb.length) {
			    /* Shuffle in the current buffer */
			    System.arraycopy(cb, markedChar, cb, 0, delta);
			    markedChar = 0;
			    dst = delta;
			} else {
			    /* Reallocate buffer to accommodate read-ahead limit */
			    char ncb[] = new char[readAheadLimit];
			    System.arraycopy(cb, markedChar, ncb, 0, delta);
			    cb = ncb;
			    markedChar = 0;
			    dst = delta;
			}
	                nextChar = nChars = delta;
		    }
		}
	
		int n;
		do {
		    n = in.read(cb, dst, cb.length - dst);
		} while (n == 0);
		if (n > 0) {
		    nChars = dst + n;
		    nextChar = dst;
		}
    }

    /**
     * 读取单个字符、以整数形式返回。如果读到in的结尾则返回-1。
     */
    public int read() throws IOException {
		synchronized (lock) {
		    ensureOpen();
		    for (;;) {
			if (nextChar >= nChars) {
			    fill();
			    if (nextChar >= nChars)
				return -1;
			}
			if (skipLF) {
			    skipLF = false;
			    if (cb[nextChar] == '\n') {
				nextChar++;
				continue;
			    }
			}
			return cb[nextChar++];
		    }
		}
    }

    /**
     * 将in中len个字符读取到cbuf从下标off开始长度len中
     */
    private int read1(char[] cbuf, int off, int len) throws IOException {
		if (nextChar >= nChars) {
		    /* If the requested length is at least as large as the buffer, and
		       if there is no mark/reset activity, and if line feeds are not
		       being skipped, do not bother to copy the characters into the
		       local buffer.  In this way buffered streams will casc