Java IO - CharArrayReader&CharArrayWriter
2016-05-25 22:04
796 查看
基本概念
CharArrayReader:此类实现一个可用作字符输入流的字符缓冲区。CharArrayWriter:此类实现一个可用作 Writer 的字符缓冲区。缓冲区会随向流中写入数据而自动增长。可使用 toCharArray() 和 toString() 获取数据。 在此类上调用 close() 无效,并且在关闭该流后可以调用此类中的各个方法,而不会产生任何 IOException。
-继承结构:分别继承了 Reader/Writer
源码分析
1.CharArrayReader
类结构结果图,通过与 ByteArrayInputStream 进行对比,发现 CharArrayReader 多了ersureOpen(),ready() 少了一个 available(),且 ready 和 available 作用相似,通过下面的源码分析会发现二者的实现原理一模一样。
成员变量
//缓冲数组 protected char buf[]; //索引位置,表示当前读取的位置 protected int pos; //标记位,只能标记当前读取的位置 protected int markedPos = 0; //要读取的字符数组的长度 protected int count;
构造函数,结合成员变量的注释一目了然
public CharArrayReader(char buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length; } 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; }
先来看看多出来的 ensureOpen() 方法
//判断缓冲数组是否为空,作用就是字面上的意思确保字符流打开不为空,否则抛出异常 private void ensureOpen() throws IOException { if (buf == null){ throw new IOException("Stream closed"); } }
read 操作,这里实现了 Reader 中定义的抽象 read 方法,原理与字节数组输入流一模一样。
//读取单个字符 public int read() throws IOException { synchronized (lock) { ensureOpen(); if (pos >= count) return -1; else return buf[pos++]; } } //将字符读入数组的某一部分 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; } //根据索引位置,判断是否到达流末尾(即缓冲区末尾) if (pos >= count) { return -1; } //判断要读取的字符数量是否超出了缓冲数组中剩余的字符数量 if (pos + len > count) { len = count - pos; } if (len <= 0) { return 0; } //重点-->将缓冲数组上的字符(从索引位置开始)复制到当前数组中 System.arraycopy(buf, pos, b, off, len); pos += len; return len; } }
skip 方法
////表示要跳跃字符数量,通过改变数组的索引位置实现 public long skip(long n) throws IOException { synchronized (lock) { ensureOpen(); if (pos + n > count) { n = count - pos; } if (n < 0) { return 0; } pos += n; return n; } }
mark/reset 方法
//只能标记当前的读取位置,与参数值无关 public void mark(int readAheadLimit) throws IOException { synchronized (lock) { ensureOpen(); markedPos = pos; } } public void reset() throws IOException { synchronized (lock) { ensureOpen(); pos = markedPos; } }
剩下的方法,只贴出源码,不做分析
public boolean markSupported() { return true; } public boolean ready() throws IOException { synchronized (lock) { ensureOpen(); return (count - pos) > 0; } } //注意与字节写入流的区别 public void close() { buf = null; }
2.CharArrayWriter
结构图,同样的与字节数组输出流没有大差别成员变量,同上,不在阐述。
构造函数,不指定数组长度时默认 32。
public CharArrayWriter() { this(32); } public CharArrayWriter(int initialSize) { if (initialSize < 0) { throw new IllegalArgumentException("Negative initial size: " + initialSize); } buf = new char[initialSize]; }
wirter 方法
//写入单个字符 public void write(int c) { synchronized (lock) { int newcount = count + 1; //判断下一次写入时长度如果超出缓冲数组的容量,则创建新的缓冲数组并将内容复制进去 if (newcount > buf.length) { buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); } buf[count] = (char) c; count = newcount; } } //写入字符数组的某一部分 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; } } //写入字符串的某一部分 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; } }
append 方法
//将指定字符添加到此 writer,并返回此 writer public CharArrayWriter append(CharSequence csq) { String s = (csq == null ? "null" : csq.toString()); write(s, 0, s.length()); return this; } //将指定字符序列添加到此 writer,并返回此 writer public CharArrayWriter append(CharSequence csq) { String s = (csq == null ? "null" : csq.toString()); write(s, 0, s.length()); return this; } //将指定字符序列的子序列添加到此 writer,并返回此 writer 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 char toCharArray()[] { synchronized (lock) { return Arrays.copyOf(buf, count); } } public String toString() { synchronized (lock) { return new String(buf, 0, count); } } public void writeTo(Writer out) throws IOException { synchronized (lock) { out.write(buf, 0, count); } } public int size() { return count; } public void reset() { count = 0; } public void flush() { } //注意与字节读取流的区别 public void close() { }
相关文章推荐
- maven搭建ssm分模块框架 (myeclipse版) (二) 较详细版
- java 基础拾漏
- 第一个算法优化例子
- Java synchronized详解
- java享元设计模式
- Java语言的发展及其特点
- Java入门篇
- 关于java中一些代码的理解
- javaSE 模拟Spring框架的Ioc
- Java系统工具jps原理解析
- Spring 计划 7.0
- Java中HashMap、TreeMap的区别
- Eclipse快捷键 10个最有用的快捷键
- java synchronized详解
- eclipse导入项目,项目名出现红叉的情况
- maven 项目提示找不到javax.servlet.xxx问题解决
- Java-equals()和toSting()用法(面向对象编程思想)
- java基本数据类型包装类
- java 单例模式 最经典的例子
- Spring整合技术之Hibernate