Java_io体系之CharArrayReader、CharArrayWriter简介、走进源码及示例――13
一:CharArrayReader
1、类功能简介:
字符数组输入流car 、与ByteArrayInputStream相同、用于将自带的内置缓存字符数组中的字符读取到程序中。与ByteArrayInputStream不同的是:当调用car的close方法是将内置缓存数组cbuffer设为null、而且car会抛出IOException异常(ensureOpen方法、即当cbuffer为null时则认为car关闭)。方法与使用功能与bais很相似、说白了区别就在于一个是从内置字节数组中读取字节、一个是从内置字符数组中读取字符。有一点是与bais不同的地方、就是他们的父类的区别、Reader比InputStream多实现一个Readable接口、这个接口要求提供一个方法、是将字符数组读取到指定的缓存数组中、其实完全可以用read(char[] cbuf, int off, int len)来代替实现。。。
2、CharArrayReader API简介:
A:关键字
protected char buf[]; 自带字符数组
protected int pos; buf中下一个要被读取的字符位置
protected int markedPos = 0; buf中被mark的字符下标
protected int count; 字符数组中总数、buf中索引为count和下一个都没有字符存在。
B:构造方法
CharArrayReader(char buf[]); 使用传入的buf构造CharArrayReader
CharArrayReader(char buf[], int offset, int length); 使用传入的buf的一部分构造CharArrayReader
C:一般方法
void close(); 关闭此流、
void mark(int readAheadLimit); 标记当前流读取的位置
void markSupport(); 检测此流是否支持标记
int read(); 读取一个字符、并以整数形式返回
int read(char[] c, int off, int len); 将buf中len个字符读取到下标从off开始的b中、返回读取的字符个数
boolean ready(); 查看CharArrayReader是否可读。
void reset(); 将此流开始位置重置到最后一次调用mark是流的读取位置
long skip(long n); 丢弃buf中n个字符、返回实际丢弃的字符个数
3、源码分析
package com.chy.io.original.code;
import java.io.IOException;
/**
* 字符数组输入流
*/
public class CharArrayReader extends Reader {
/** 自带字符数组 */
protected char buf[];
/** buf中下一个要被读取的字符位置 */
protected int pos;
/** buf中被mark的字符下标 */
protected int markedPos = 0;
/**
* 字符数组中总数、buf中索引为count和下一个都没有字符存在。
*/
protected int count;
/**
* 使用传入的buf构造CharArrayReader、并初始化CharArrayReader的buf、以及buf中将要被读取的字符的下标及总数。
*/
public CharArrayReader(char buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
/**
* 使用传入的buf构造CharArrayReader、并初始化CharArrayReader的buf、以及buf中将要被读取的字符的下标及总数。
*/
public CharArrayReader(char buf[], int offset, int length) {
if ((offset < 0) || (offset > buf.length) || (length < 0) ||
((offset + length) < 0)) {
throw new IllegalArgumentException();
}
this.buf = buf;
this.pos = offset;
this.count = Math.min(offset + length, buf.length);
this.markedPos = offset;
}
/** 检测此流是否关闭、看此流的close()方法就能明白这个方法*/
private void ensureOpen() throws IOException {
if (buf == null)
throw new IOException("Stream closed");
}
/**
* 读取单个字符
*/
public int read() throws IOException {
synchronized (lock) {
ensureOpen();
if (pos >= count)
return -1;
else
return buf[pos++];
}
}
/**
* 将buf中len个字符读取到下标从off开始的b中、返回读取的字符个数。
*/
public int read(char b[], int off, int len) throws IOException {
synchronized (lock) {
ensureOpen();
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
//buf中没有字符
if (pos >= count) {
return -1;
}
//buf中字符不够len个
if (pos + len > count) {
len = count - pos;
}
//传入的len<=0、返回0
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
}
/**
* 丢弃buf中n个字符、返回实际丢弃的字符个数。
*/
public long skip(long n) throws IOException {
synchronized (lock) {
ensureOpen();
//如果buf中剩余字符不够n个、丢弃buf中现有所有字符
if (pos + n > count) {
n = count - pos;
}
//传入的n为负、不丢弃。
if (n < 0) {
return 0;
}
pos += n;
return n;
}
}
/**
* 查看CharArrayReader是否可读。判断条件是buf中是否还有字符存在。
*/
public boolean ready() throws IOException {
synchronized (lock) {
ensureOpen();
return (count - pos) > 0;
}
}
/**
* 是否支持mark?是
*/
public boolean markSupported() {
return true;
}
/**
* 标记当前buf中下一个将要被读取的字符下标。
* 传入的readAheadLimit同ByteArrayInputStream一样、无效。
*/
public void mark(int readAheadLimit) throws IOException {
synchronized (lock) {
ensureOpen();
markedPos = pos;
}
}
/**
* 将此流开始位置重置到最后一次调用mark是流的读取位置。
*/
public void reset() throws IOException {
synchronized (lock) {
ensureOpen();
pos = markedPos;
}
}
/**
* 关闭、清空buf。
*/
public void close() {
buf = null;
}
}
4、实例演示:
参见下面的实例演示、一般喜欢将两者放在一个测试类中、分成两个方法testCharArrayReader()、testCharArrayWriter()、有关联的两个类还会多出关联测试、这样有条理点。
二:CharArrayWriter
1、类功能简介:
字符数组输出流caw、用于将字符写入到内置字符缓存数组char[] buf中、当此数组存放满员时会自动扩容、同样与ByteArrayOutputStream相比他也提供了几个操作buf中字符的方法、可使用 toCharArray() 和 toString() 获取数据、还可使用writeTo(Writer out)将buf写入到底层流中。同样在此类上调用 close()、flush()无效,不会产生IOException、并且在关闭该流后仍然可以调用此类中的各个方法。