`
810364804
  • 浏览: 787548 次
文章分类
社区版块
存档分类
最新评论

Java_io体系之Writer、Reader简介、走进源码——12

 
阅读更多

Java_io体系之Writer、Reader简介、走进源码——12

一:Writer


1、类功能简介:


字符输出流、本身是一个抽象类、是所有字符输出流的父类、与OutputStream相同的是、定义了所有字符输出流的标准、和一些必须具有的基本方法、和简单的实现其中有三个抽象方法必须要我们去实现的是write(char[] cbuf, int off, int len)、flush()、close()、子类可以根据自己要达到的效果或者功能、重写或者添加新的方法;与OutputStream不同的是Writer有个自带的缓存字符数组writerBuffer、它不是直接将字符写入到字符输出流管道中的、而是先放在writerBuffer中、操作单位不一样、Writer换成了对字符的操作。

2、Writer API简介:

A:关键字

    private char[] writeBuffer;		字符缓存数组、用于临时存放要写入字符输出流管道中的字符、

    private final int writeBufferSize = 1024;	字符缓存数组的默认大小、
    
    protected Object lock;	用于同步针对此流的操作的对象、


B:构造方法

	protected Writer();		创建一个新的字符流、其关键部分将同步writer自身
	
	protected Writer(Object obj);		创建一个新的字符流、其关键部分将同步obj自身


C:一般方法


	Writer append(char c);		将指定字符追加到Writer中
	
	Writer append(CharSequence csq);	将指定字符序列添加到此 writer。 
	
	Writer append(CharSequence csq, int start, int end)	将指定字符序列的子序列添加到此 writer.Appendable。 
	
	abstract  void close();		关闭此流
	
	abstract void flush();		刷新该流的缓冲
	
	abstract  void write(char[] cbuf, int off, int len);	写入字符数组的某一部分。 
	
	void write(int c);		写入单个字符。 
	
	void write(String str);		写入字符串。 
	
	void write(String str, int off, int len);		写入字符串的某一部分。 


3、源码分析

package com.chy.io.core;

import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;


/**
 */

public abstract class Writer implements Appendable, Closeable, Flushable {

	//字符缓存数组、用于临时存放要写入字符输出流管道中的字符、
    private char[] writeBuffer;

    
    //字符缓存数组的默认大小、
    private final int writeBufferSize = 1024;

    //用于同步针对此流的操作的对象、
    protected Object lock;	

    //创建一个新的字符流、其关键部分将同步writer自身
    protected Writer() {
    	this.lock = this;
    }

    //创建一个新的字符流、其关键部分将同步obj自身
    protected Writer(Object lock) {
		if (lock == null) {
		    throw new NullPointerException();
		}
		this.lock = lock;
    }
    /**
     * 将一个字符以整数形式写入到缓存字符数组writerBuffer中
     */
    public void write(int c) throws IOException {
		synchronized (lock) {
		    if (writeBuffer == null){
			writeBuffer = new char[writeBufferSize];
		    }
		    writeBuffer[0] = (char) c;
		    write(writeBuffer, 0, 1);
		}
    }

    /**
     * 将一个字符数组写入到writerBuffer中 
     */
    public void write(char cbuf[]) throws IOException {
    	write(cbuf, 0, cbuf.length);
    }

    /**
     * 抽象类:将一个字符数组的一部分写入到当前流的管道中。
     */
    abstract public void write(char cbuf[], int off, int len) throws IOException;

    /**
     * 将一个字符串写入到当前流管道中
     */
    public void write(String str) throws IOException {
    	write(str, 0, str.length());
    }

    /**
     * 将一个字符串的一部分写入到当前流的管道中
     */
    public void write(String str, int off, int len) throws IOException {
		synchronized (lock) {
		    char cbuf[];
		    if (len <= writeBufferSize) {
			if (writeBuffer == null) {
			    writeBuffer = new char[writeBufferSize];
			}
			cbuf = writeBuffer;
		    } else {	// Don't permanently allocate very large buffers.
			cbuf = new char[len];
		    }
		    str.getChars(off, (off + len), cbuf, 0);
		    write(cbuf, 0, len);
		}
    }

    /**
     * 将一个字符有序数列追加到当前流管道中、返回当前流对象
     */
    public Writer append(CharSequence csq) throws IOException {
	if (csq == null)
	    write("null");
	else
	    write(csq.toString());
    	return this;
    }

    /**
     * 将一个字符有序数列的一部分追加到当前流管道中、返回当前流对象
     */
    public Writer append(CharSequence csq, int start, int end) throws IOException {
		CharSequence cs = (csq == null ? "null" : csq);
		write(cs.subSequence(start, end).toString());
 	return this; 
    }

    /**
     * 将一个字符追加到当前流管道中、返回当前流对象
     */
    public Writer append(char c) throws IOException {
		write(c);
		return this;
    }

    /**
     * flush当前流、要求子类必须重写
     */
    abstract public void flush() throws IOException;

    /**
     * 当前流、要求子类必须重写
     */
    abstract public void close() throws IOException;

}


二:Reader

1、类功能简介:


用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。


2、Reader API简介:

A:关键字

    protected Object lock;		用于同步针对此流的操作的对象。


B:构造方法

	protected Reader();		创建一个新的字符流 reader,其重要部分将同步其自身的 reader。
	
	protected Reader(Object obj);		创建一个新的字符流 reader,其重要部分将同步给定的对象。
	


C:一般方法

	abstract void close();		关闭此流、释放与此流有关的所有资源
	
	boolean markSupported();	 检测此流是否支持标记	
	
	void mark(int readAheadLimit);		标记此流、与reset()结合使用
	
	void reset();		将流的读取位置重置到最后一次调用mark方法时的位置
	
	boolean ready();		检测此流是否可读
	
	int read(java.nio.CharBuffer target);		将输入流管道中的target.length个字节读取到指定的缓存字符数组target中、返回实际存放到target中的字符数。
	
	int read();		读取一个字符并返回
	
	int read(char[] cbuf);		将字符读取到cbuf中、返回实际读取到的字符数。
	
	abstract int read(char[] cbuf, int off, int len);		抽象类:将字符读取到下标冲off开始、len个后续位置的cbuf中。
	
	long skip(long n);		从剩余有效字符中跳过n个

3、源码分析

package com.chy.io.core;

import java.io.Closeable;
import java.io.IOException;


/**
 * Reader:字符输入流、本身是抽象类、为所有字符输入流类提供一个标准、和基本方法及简单实现、与InputStream相比、多实现一个Readble接口、
 * 支持将字符读取到指定的缓存字符数组中。要求子类重写read(char[] cbuf, int off, int len)、close()、这两个方法、一般子类都会重写Reader提供的方法
 * 或者部分方法、也可能添加新的方法来体现自己的特色。与InputStream的本质区别就是操作单位不同、由字节变为字符。
 */

public abstract class Reader implements Readable, Closeable {
    /**
     * 用于同步针对此流的操作的对象。
     */
    protected Object lock;

    /**
     * 创建一个新的字符流 reader,其重要部分将同步其自身的 reader。
     */
    protected Reader() {
    	this.lock = this;
    }

    /**
     * 创建一个新的字符流 reader,其重要部分将同步给定的对象。
     */
    protected Reader(Object lock) {
		if (lock == null) {
		    throw new NullPointerException();
		}
		this.lock = lock;
    }

    /**
     * 将输入流管道中的target.length个字节读取到指定的缓存字符数组target中、返回实际存放到target中的字符数。
     */
    public int read(java.nio.CharBuffer target) throws IOException {
        int len = target.remaining();
        char[] cbuf = new char[len];
        int n = read(cbuf, 0, len);
        if (n > 0)
            target.put(cbuf, 0, n);
        return n;
    }

    /**
     * 读取一个字符并返回
     */
    public int read() throws IOException {
		char cb[] = new char[1];
		if (read(cb, 0, 1) == -1)
		    return -1;
		else
		    return cb[0];
    }

    /**
     * 将字符读取到cbuf中、返回实际读取到的字符数。
     */
    public int read(char cbuf[]) throws IOException {
    	return read(cbuf, 0, cbuf.length);
    }

    /**
     * 抽象类:将字符读取到下标冲off开始、len个后续位置的cbuf中。
     */
    abstract public int read(char cbuf[], int off, int len) throws IOException;

    /** 最大允许跳过字符数 */
    private static final int maxSkipBufferSize = 8192;

    /** 用于skip方法临时存放字符 */
    private char skipBuffer[] = null;

    /**
     * 从剩余有效字符中跳过n个
     */
    public long skip(long n) throws IOException {
		if (n < 0L) 
		    throw new IllegalArgumentException("skip value is negative");
		int nn = (int) Math.min(n, maxSkipBufferSize);
		synchronized (lock) {
		    if ((skipBuffer == null) || (skipBuffer.length < nn))
			skipBuffer = new char[nn];
		    long r = n;
		    while (r > 0) {
			int nc = read(skipBuffer, 0, (int)Math.min(r, nn));
			if (nc == -1)
			    break;
			r -= nc;
		    }
		    return n - r;
		}
    }

    /** 检测此流是否可读*/
    public boolean ready() throws IOException {
    	return false;
    }

    /** 检测此流是否支持标记*/
    public boolean markSupported() {
    	return false;
    }

    /** 标记此流、与reset()结合使用*/
    public void mark(int readAheadLimit) throws IOException {
    	throw new IOException("mark() not supported");
    }

    /** 将流的读取位置重置到最后一次调用mark方法时的位置*/
    public void reset() throws IOException {
    	throw new IOException("reset() not supported");
    }

    /** 关闭此流、释放与此流有关的所有资源*/
     abstract public void close() throws IOException;

}


总结:

通过两组对比来观察一下相同与区别

OutputStream/InputStream VS Writer/Reader

相同:

都是抽象类、为所有子类提供标准、和基本的方法及简单实现、关键方法是抽象方法、要子类根据自己的特色去实现

其他读写方法都是以这个关键方法为核心实现的、Reader/InputStream都继承了closeable接口。

Writer/OutputStream都继承了Closeable,Flushable

区别:

本质区别——操作的对象不同。字节流针对的是字节、字符流针对的是字符

Reader相比与InputStream多实现了一个Readable接口、用于提供一个可以将字符写入到指定缓存数组的方法

同时两者用于实现读取的关键抽象方法、reader.read(char[] cbuf,int off, int len)、inputStream.read();

一个是针对字符数组、一个是针对单个字节、其他的读取方法都是以这两个方法为核心的。

还有一个区别就是两者的close()方法类型不一样、Reader的close方法是抽象类、必须要子类重写、

InputStream.close不是抽象类、子类可以重写、也可不重写。

Writer相比与OutputStream多实现了一个Appendable接口、用于向此流中追加字符。两者用于读取的关键方法也是一个针对字符数组、一个针对字节

并且Writer的close()、flush()方法都是抽象类、必须要子类实现具有自己的特色。


更多IO内容:java_io 体系之目录


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics