Java
Java IO

Java IO 18 - CharArrayWriter详解

简介:流是一组有顺序的,有起点和终点的字节集合。是对设备文件间数据传输的总称和抽象。

1. CharArrayWriter介绍

CharArrayReader用于写入数据符,它继承于Writer,操作的数据是以字符为单位。

2. CharArrayWriter函数列表

  • CharArrayWriter()
  • CharArrayWriter(int initialSize)
  • CharArrayWriter append(CharSequence csq, int start, int end)
  • CharArrayWriter append(char c)
  • CharArrayWriter append(CharSequence csq)
  • void close()
  • void flush()
  • void reset()
  • int size()
  • char[] toCharArray()
  • String toString()
  • void write(char[] buffer, int offset, int len)
  • void write(int oneChar)
  • void write(String str, int offset, int count)
  • void writeTo(Writer out)

3. Writer源码分析

Writer是CharArrayWriter的父类,我们先看看Writer的源码,然后再学CharArrayWriter的源码。下面是Writer类的源码,基于JDK 1.7.0_07:

  • package java.io;
  • public abstract class Writer implements Appendable, Closeable, Flushable {
  • // 写出缓冲区
  • private char[] writeBuffer;
  • // 默认的写出缓冲区大小
  • private final int writeBufferSize = 1024;
  • // 锁
  • protected Object lock;
  • protected Writer() {
  • this.lock = this;
  • }
  • protected Writer(Object lock) {
  • if (lock == null) {
  • throw new NullPointerException();
  • }
  • this.lock = lock;
  • }
  • // 写出一个字符
  • public void write(int c) throws IOException {
  • synchronized (lock) {
  • if (writeBuffer == null){
  • writeBuffer = new char[writeBufferSize];
  • }
  • // 先将字符放在writeBuffer中
  • writeBuffer[0] = (char) c;
  • // 再使用write方法将writeBuffer写出
  • write(writeBuffer, 0, 1);
  • }
  • }
  • // 写出一个字符数组
  • 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());
  • }
  • // 写出一个字符串从off开始的len个字符
  • 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];
  • }
  • // 将字符串从off开始的len个字符拷贝到cbuf中
  • str.getChars(off, (off + len), cbuf, 0);
  • // 然后通过write方法写出
  • write(cbuf, 0, len);
  • }
  • }
  • // 将指定的字符串序列添加到Writer中,会将其转换为String后写出
  • public Writer append(CharSequence csq) throws IOException {
  • if (csq == null)
  • write("null");
  • else
  • write(csq.toString());
  • return this;
  • }
  • // 将指定的字符串序列的[start, end)区间的子序列添加到Writer中,会将其转换为String后写出
  • 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;
  • }
  • // 将字符c添加到Writer中,会将其写出
  • public Writer append(char c) throws IOException {
  • write(c);
  • return this;
  • }
  • abstract public void flush() throws IOException;
  • abstract public void close() throws IOException;
  • }

4. CharArrayWriter源码分析

下面是CharArrayWriter类的源码,基于JDK 1.7.0_07:

  • package java.io;
  • import java.util.Arrays;
  • public class CharArrayWriter extends Writer {
  • // 字符数组缓冲
  • protected char buf[];
  • // 下一个字符的写入位置
  • protected int count;
  • // 构造函数:默认缓冲区大小是32
  • public CharArrayWriter() {
  • this(32);
  • }
  • // 构造函数:指定缓冲区大小是initialSize
  • public CharArrayWriter(int initialSize) {
  • if (initialSize < 0) {
  • throw new IllegalArgumentException("Negative initial size: " + initialSize);
  • }
  • buf = new char[initialSize];
  • }
  • // 写入一个字符c到CharArrayWriter中
  • public void write(int c) {
  • synchronized (lock) {
  • int newcount = count + 1;
  • if (newcount > buf.length) {
  • // 扩容操作
  • // 会创建一个大小为Math.max(buf.length << 1, newcount)的新buf数组,
  • // 然后将旧buf数组中的数据复制到新buf数组中,并返回新buf数组
  • buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
  • }
  • buf[count] = (char)c;
  • count = newcount;
  • }
  • }
  • // 写入字符数组c到CharArrayWriter中,off是字符数组b中的起始写入位置,len是写入的长度
  • public void write(char c[], int off, int len) {
  • 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;
  • if (newcount > buf.length) {
  • buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
  • }
  • System.arraycopy(c, off, buf, count, len);
  • count = newcount;
  • }
  • }
  • // 写入字符串str到CharArrayWriter中,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;
  • }
  • }
  • // 将CharArrayWriter写入到Writer对象out中
  • public void writeTo(Writer out) throws IOException {
  • synchronized (lock) {
  • out.write(buf, 0, count);
  • }
  • }
  • // 将csq写入到CharArrayWriter中
  • // 注意:该函数返回CharArrayWriter对象
  • public CharArrayWriter append(CharSequence csq) {
  • String s = (csq == null ? "null" : csq.toString());
  • write(s, 0, s.length());
  • return this;
  • }
  • // 将csq从start开始(包括)到end结束(不包括)的数据,写入到CharArrayWriter中。
  • // 注意:该函数返回CharArrayWriter对象
  • 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;
  • }
  • // 将字符c追加到CharArrayWriter中!
  • // 注意:它与write(int c)的区别。append(char c)会返回CharArrayWriter对象。
  • public CharArrayWriter append(char c) {
  • write(c);
  • return this;
  • }
  • // 重置
  • public void reset() {
  • count = 0;
  • }
  • // 将CharArrayWriter的全部数据对应的char[]返回
  • public char toCharArray()[] {
  • synchronized (lock) {
  • return Arrays.copyOf(buf, count);
  • }
  • }
  • // 返回CharArrayWriter的大小
  • public int size() {
  • return count;
  • }
  • public String toString() {
  • synchronized (lock) {
  • return new String(buf, 0, count);
  • }
  • }
  • public void flush() { }
  • public void close() { }
  • }

CharArrayWriter实际上是将数据写入到它内部维护的字符缓冲数组中,当调用writeTo(OutputStream out)会将字符缓冲数组中的数据写入到out流中,当调用toString()会将字符缓冲数组中的数据转换为字符串并返回。

  1. 通过CharArrayWriter()创建的CharArrayWriter对应的字符缓冲数组大小是32。
  2. 通过CharArrayWriter(int size)创建的CharArrayWriter对应的字符缓冲数组大小是size
  3. write(int oneChar)的作用将int类型的oneChar换成char类型,然后写入到CharArrayWriter中。
  4. write(char[] buffer, int offset, int len)是将字符数组buffer写入到字符缓冲数组中,offset是从buffer中读取数据的起始偏移位置,len是读取的长度。
  5. write(String str, int offset, int count)是将字符串str写入到输出流中,offset是从str中读取数据的起始位置,count是读取的长度。
  6. append(char c)的作用将char类型的c写入到CharArrayWriter的字符缓冲数组中,然后返回CharArrayWriter对象。注意:append(char c)write(int c)都是将单个字符写入到CharArrayWriter中,它们的区别是,append(char c)会返回CharArrayWriter对象,但是write(int c)返回void。
  7. append(CharSequence csq, int start, int end)的作用将csqstart开始(包括)到end结束(不包括)的数据,写入到CharArrayWriter中。该函数返回CharArrayWriter对象。
  8. append(CharSequence csq)的作用将csq写入到CharArrayWriter中。该函数返回CharArrayWriter对象!
  9. writeTo(OutputStream out)将该字符缓冲数组的数据全部写入到输出流out中。

5. CharArrayWriter示例

  • public static void main(String[] args) throws IOException {
  • CharArrayWriter charArrayWriter = new CharArrayWriter(32);
  • charArrayWriter.write('h');
  • charArrayWriter.write('e');
  • charArrayWriter.write("llo");
  • charArrayWriter.write(", world\n");
  • charArrayWriter.append("sequence: ").append(new CharSequence() {
  • private String innerString = "abcdefghijklmnopqrstuvwxyz";
  • @Override
  • public int length() {
  • return innerString.length();
  • }
  • @Override
  • public char charAt(int index) {
  • return innerString.charAt(index);
  • }
  • @Override
  • public CharSequence subSequence(int start, int end) {
  • return innerString.subSequence(start, end);
  • }
  • }, 7, 20);
  • System.out.println("toString: \n" + charArrayWriter.toString());
  • CharArrayWriter charArrayWriter1 = new CharArrayWriter();
  • System.out.println("-------------------------");
  • charArrayWriter.writeTo(charArrayWriter1);
  • System.out.println("writeTo: \n" + charArrayWriter1.toString());
  • }

运行结果如下:

  • toString:
  • hello, world
  • sequence: hijklmnopqrst
  • -------------------------
  • writeTo:
  • hello, world
  • sequence: hijklmnopqrst