一、CharArrayWriter的介绍
CharWriter继承自java.io.Writer,内部实现了一个可用于保存写入字符数据的字符缓冲区,CharArrayWriter中缓冲区会随着流中写入数据的增加而自动扩容。流中的保存的字符数据可以跳过调用CharArrayWriter的toCharArray()或者toString()方法获取。
二、CharArray成员变量
package java.io;import java.util.Arrays;publicclass CharArrayWriter extends Writer { /** * 字符缓存区,保存写入的字符数据 */ protected char buf[]; /** * 缓冲区中保存的有效字符个数 */ protected int count;}
三、CharArrayWriter源码分析
1 - 构造函数
/** 构造函数,缓冲区数组长度默认为32 **/ public CharArrayWriter() { this(32); } /** * 构造函数,缓冲区数组长度为指定参数initialSize */ public CharArrayWriter(int initialSize) { if (initialSize < 0) { throw new IllegalArgumentException("Negative initial size: " + initialSize); } buf = new char[initialSize]; }
构造函数做的事情很简单就是初始化内部缓冲区
2 - void write(int c)方法 - 写入一个字符
public void write(int c) { synchronized (lock) { //计算写入字符后的缓冲区要保存的字符个数 int newcount = count + 1; //如果缓冲区已满,则创建一个新的char数组,数组长度扩容为原来的2倍,将当前缓冲区字符数据复制到新数组,并更 //新缓冲区数组引用buf完成数组扩容 if (newcount > buf.length) { buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); } //在新缓冲区数组写入位置插入指定字符c buf[count] = (char)c; //更新写入字符个数count count = newcount; } }
写入单个指定字符的write(int c)方法逻辑很简单,首先判断插入字符后缓冲区是否需要扩容,如果需要那么在不超出Integer.MAX_VALUE的限制下扩容为原来的2倍,将原来缓冲区数组的数据复制到扩容后的新数组,更新对象内部的缓冲区数组引用buf,完成数组扩容,然后在扩容后的缓冲区插入指定字符c,并更新字符个数count。其他像是write(char[] ch, int off, int len)与write(String str, int off, int len)方法逻辑类似,区别只在于方法一次调用插入单个字符与多个字符的区别。
3 - 其他成员方法
package java.io;import java.util.Arrays;publicclass CharArrayWriter extends Writer { /** * 将字符数组c从off开始的len个字符写入CharArrayReader缓冲区中 */ public void write(char c[], int off, int len) { //写入数组c相关参数的范围合法性校验 if ((off < 0) || (off > c.length) || (len < 0) || ((off + len) > c.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } synchronized (lock) { int newcount = count + len; //如果写入后缓冲区会溢出则对缓冲区buf扩容 if (newcount > buf.length) { buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); } //将指定数组c的写入部分(off开始的len个字符)复制到新缓冲区数组中 System.arraycopy(c, off, buf, count, len); count = newcount; } } /** * 将字符串str中从索引off开始的len个字符写入到缓冲区中,在str.getChars内部会进行写入指定字符串写入位置off和 * len范围的合法性校验以及校验成功后的数据填充(也是基于系统的数组数据复制方法) */ public void write(String str, int off, int len) { synchronized (lock) { int newcount = count + len; if (newcount > buf.length) { buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); } str.getChars(off, off + len, buf, count); count = newcount; } } /** * 将缓冲区的字符数据写入到另一个字符流out */ public void writeTo(Writer out) throws IOException { synchronized (lock) { out.write(buf, 0, count); } } /** * 将指定字符序列添加到当前字符输出流,其实就是将字符序列中的字符数据写入到缓冲区中,并返回当前当前字符输出流对象 */ public CharArrayWriter append(CharSequence csq) { String s = (csq == null ? "null" : csq.toString()); write(s, 0, s.length()); return this; } /** * 将指定序列csq的子序列start到end部分字符数据写入到当前字符输出流内部缓冲区,并返回当前当前字符输出流对象 */ public CharArrayWriter append(CharSequence csq, int start, int end) { String s = (csq == null ? "null" : csq).subSequence(start, end).toString(); write(s, 0, s.length()); return this; } /** * 将指定字符写入到当前字符输出流内部缓冲区,并返回当前当前字符输出流对象 */ public CharArrayWriter append(char c) { write(c); return this; } /** * 重置该缓冲区,以便再次使用,而无需因为空间不足创建一个更大的缓冲数组丢弃原有将溢出的缓冲区 */ public void reset() { count = 0; } /** * 返回内部缓冲区数组的副本 */ public char toCharArray()[] { synchronized (lock) { return Arrays.copyOf(buf, count); } } /** * 返回当前缓冲区的有效字符个数 */ public int size() { return count; } /** * 将当前字符输出流内部缓冲区保存的写入字符数据转换为字符串返回 */ public String toString() { synchronized (lock) { return new String(buf, 0, count); } } /** * 刷新流,无效函数 */ public void flush() { } /** * 关闭流,无效函数 */ public void close() { }}