转载自   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、并且在关闭该流后仍然可以调用此类中的各个方法。

2、CharArrayWriter  API简介:

A:关键字

protected char buf[];   用于存放写入CharArrayWriter的字符、存满自动扩容。
protected int count;    buf中现有的字符数

B:构造方法

public CharArrayWriter()    使用默认buf大小创建CharArrayWriter。
public CharArrayWriter(int initialSize)     使用指定的buf大小创建CharArrayWriter。 

C:一般方法

CharArrayWriter append(CharSequence csq)    将一串有序字符序列写入buf中  CharArrayWriter append(CharSequence csq, int start, int end)     将一串有序字符序列的一部分写入buf中  CharArrayWriter append(char c)      将一个字符写入buf中  void close()    关闭此流(没有效果)  void flush()    flush此流(没有效果)  void reset()    清空buf、重头开始  int size()      查看当前buf中字符总数  char[] toCharArray()    将buf中内容转换成char[]  String toString()   将buf中字符转换成String返回  void write(int c)   写入一个字符。  void write(char c[], int off, int len)      将一个char[]的一部分写入buf中、若buf满、扩容。  void write(String str, int off, int len)    将一个字符串写入buf中、满自动扩容  void writeTo(Writer out)    将buf中现有的字节写入到subWriter(out)中  

3、源码分析

package com.chy.io.original.code;  import java.io.IOException;
import java.util.Arrays;  /** * Writer的一个子类、可将字符写入到自带的一个缓存字符数组buf中、 * 当buf写满时、会自动扩容。 */
public class CharArrayWriter extends Writer {  /** * 用于存放写入CharArrayWriter的字符、存满自动扩容。 */  protected char buf[];  /** * buf中现有的字符数 */  protected int count;  /** * 使用默认buf大小创建CharArrayWriter。 */  public CharArrayWriter() {  this(32);  }  /** * 使用指定的buf大小创建CharArrayWriter。 */  public CharArrayWriter(int initialSize) {  if (initialSize < 0) {  throw new IllegalArgumentException("Negative initial size: "  + initialSize);  }  buf = new char[initialSize];  }  /** * 写入一个字符。 */  public void write(int c) {  synchronized (lock) {  int newcount = count + 1;  //如果buf存满、则将buf容量扩大1倍、并将原来buf中count字符copy到新的buf中  if (newcount > buf.length) {  buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));  }  //将新写入的字符存入到buf第count个下标位置。  buf[count] = (char)c;  count = newcount;  }  }  /** * 将一个char[]的一部分写入buf中、若buf满、扩容。 */  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;  }  }  /** * 将一个字符串写入buf中、满自动扩容 */  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;  }  }  /** * 将buf中现有的字节写入到subWriter(out)中 */  public void writeTo(Writer out) throws IOException {  synchronized (lock) {  out.write(buf, 0, count);  }  }  /** * 将一串有序字符序列写入buf中 */  public CharArrayWriter append(CharSequence csq) {  String s = (csq == null ? "null" : csq.toString());  write(s, 0, s.length());  return this;  }  /** * 将一串有序字符序列的一部分写入buf中 */  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;  }  /** * 将一个字符写入buf中 */  public CharArrayWriter append(char c) {  write(c);  return this;  }  /** * 清空buf、重头开始 */  public void reset() {  count = 0;  }  /** * 将buf中内容转换成char[] */  public char toCharArray()[] {  synchronized (lock) {  return Arrays.copyOf(buf, count);  }  }  /** * 查看当前buf中字符总数 */  public int size() {  return count;  }  /** * 将buf中字符转换成String返回 */  public String toString() {  synchronized (lock) {  return new String(buf, 0, count);  }  }  /** * flush  CharArrayWriter、因此方法对CharArrayWriter没有效果、所以方法体是空! */  public void flush() { }  /** * 同样、关闭CharArrayWriter没有用、调用close()关闭此流、此流的方法一样能用。 */  public void close() { }  }  

4、实例演示:

package com.chy.io.original.test;  import java.io.BufferedReader;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
/** *  * @author      andyChen * @version     1.1 , 13/11/15 * */
public class CharArrayTest {  private static final String str = "abcdefghijklmnopqrstuvwxyz";  private static char[] charArray = new char[26];  static{  for(int i=0; i<str.length(); i++){  charArray[i] = str.charAt(i);  }  }  private static void testCharArrayReader() throws IOException{  CharArrayReader car = new CharArrayReader(charArray);  if(!car.ready()){  return;  }  /** * 与ByteArrayInputStream差不多、区别就是一个字节一个字符。 * 不爽的地方在于CharArrayReader没有提供 car.available()方法、不能随时知道buf中还有多少可以读取的字符. */  //将写入CharArrayReader内置字符缓存数组buf中的第一个字符输出、并且标记buf下一个可读字符索引的pos++  System.out.println((char)car.read());  //读取CharArrayReader中buf字符、返回实际读取的字符数。  char[] buf = new char[5];  car.read(buf, 0, 5);  printChar(buf);  //标记当前CharArrayReader流的位置、当下次调用reset后继续使用CharArrayReader读取时从此标记的位置开始读取。  //即用 markedPos记录当前的pos  car.mark(0);  //丢弃从buf下一个将要读取的字符开始的10个字符、返回实际丢弃的字符。  car.skip(10);  //读取10个字符  char[] buf2 = new char[10];  car.read(buf2, 0, 10);  printChar(buf2);  //查看buf中是否还有有效可供读取的字符  System.out.println(car.ready());  //重置mark标记的位置、即将markedPos的值重新赋给pos、这样当读取下一个字符时就是读取buf的索引为pos的字符。  car.reset();  System.out.println((char)car.read());  }  private static void testCharArrayWriter() throws IOException{  File file = new File("D:\\caw.txt");  CharArrayWriter caw = new CharArrayWriter();  //将第一个 a-z 字符写入caw内置buf中  for(int i=0; i<charArray.length; i++){  caw.write(charArray[i]);  }  caw.write("\r\n");  //将第二个a-z字符写入caw内置buf中  caw.write(charArray, 0, charArray.length);  caw.write("\r\n");  //将第三个a-z字符写入buf中  caw.write(charArray);  caw.write("\r\n");  //将第四个a-z字符写入buf中  caw.write(new String(charArray), 0, charArray.length);  caw.write("\r\n");  //将第五个a-z字符写入buf中  for(int i=0; i<charArray.length; i++){  caw.append(charArray[i]);  }  caw.append("\r\n");  //此方法传入的是一个CharSequence、CharArray是一个CharSequence的一个子类、但是为什么不行?  //caw.append(charArray);  //caw.append("\r\n");  //将第六个a-z字符写入buf中  caw.append(new StringBuffer(new String(charArray)));  caw.append("\r\n");  /** * 简单说明:caw.append()传入的参数时CharSequence、char * 但是上面传入的String、StringBuffer、StringBuilder也行、很简单、他们是CharSequence接口的实现类。 */  String aboveResult = caw.toString();  char[] buf = caw.toCharArray();  System.out.println("String aboveResult: "+ "\r\n" + aboveResult);  System.out.println("=====================================");  System.out.println("char[] result : " + "\r\n" +new String(buf));  FileWriter fw = new FileWriter(file);  caw.writeTo(fw);  fw.flush();  fw.close();  }  /** * 将写入文件的中文读取出来 * 这里没有什么组织性、 * 自己可以尝试不同组合的读取、加深理解。 */  private static void test() throws FileNotFoundException, IOException {  File file = new File("D:\\bos.txt");  FileOutputStream fos = new FileOutputStream(file);  FileInputStream fis = new FileInputStream(file);  fos.write("陈华应".getBytes());  fos.flush();  fos.close();  BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));  char[] cbuf = new char[fis.available()];  br.read(cbuf);  CharArrayReader car = new CharArrayReader(cbuf);  char[] newCbuf = new char[fis.available()];  car.read(newCbuf);  System.out.println(new String (newCbuf));  }  private static void printChar(char[] buf){  for(char c : buf ){  System.out.print(c);  }  System.out.println();  }  public static void main(String[] args) throws Exception{  testCharArrayWriter();  testCharArrayReader();  test();  }
}  

总结:

本质是将字符写入内置字符缓存数组中、或者是将字符从内置缓存数组读取到程序中(内置字符缓存数组中字符的来源是在构造CharArrayReader时传入的字符数组)。

Java_io体系之CharArrayReader、CharArrayWriter简介、走进源码及示例——13相关推荐

  1. Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例——16

    Java_io体系之BufferedWriter.BufferedReader简介.走进源码及示例--16 一:BufferedWriter 1.类功能简介: BufferedWriter.缓存字符输 ...

  2. Java_io体系之RandomAccessFile简介、走进源码及示例——20

    Java_io体系之RandomAccessFile简介.走进源码及示例--20 RandomAccessFile 1.       类功能简介: 文件随机访问流.关心几个特点: 1.他实现的接口不再 ...

  3. Java_io体系之PipedInputStream、PipedOutputStream简介、走进源码及示例——06

    Java_io体系之PipedInputStream/PipedOutputStream简介.走进源码及示例--06 --管道输出流.必须建立在管道输入流之上.所以先介绍管道输出流.可以先看源码或者总 ...

  4. Java_io体系之PipedWriter、PipedReader简介、走进源码及示例——14

    Java_io体系之PipedWriter.PipedReader简介.走进源码及示例--14 --管道字符输出流.必须建立在管道输入流之上.所以先介绍管道字符输出流.可以先看示例或者总结.总结写的有 ...

  5. linux内核体系学习路径_Linux内核分析(一)linux体系简介|内核源码简介|内核配置编译安装...

    从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底,同时在博文中如果那些地方有问题还请各位大神为我讲解. 今天我们会分析到以下内容: 1. Linux体系结构简介 ...

  6. ThreadLocal 简介 案例 源码分析 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  7. Java生鲜电商平台-电商会员体系系统的架构设计与源码解析

    Java生鲜电商平台-电商会员体系系统的架构设计与源码解析 说明:Java生鲜电商平台中会员体系作为电商平台的基础设施,重要性不容忽视.我去年整理过生鲜电商中的会员系统,但是比较粗,现在做一个最好的整 ...

  8. 编译器 llvm clang 源码转换示例

    编译器 llvm clang 源码转换示例 从git获取llvm项目的源码方式: git clone https://github.com/llvm/llvm-project.git 下载源码后,进入 ...

  9. H5音乐播放器(包含源码与示例)

    H5音乐播放器(包含源码与示例) 基于Angular+ionic的H5音乐播放器,源码:https://gitee.com/CrimsonHu/h5-music-player 示例地址 建议使用原版c ...

最新文章

  1. 7 款可替代 top 命令的工具!(二)
  2. Java 中商业运算必备的精确运算类:BigDecimal
  3. 如何用python画爱心型线_python怎么画爱心
  4. 1 python基础
  5. Spring Boot中使用@JsonComponent
  6. 自动化部署kvm虚拟机_自动化虚拟助手
  7. 乐高无限无法连接到服务器,乐高无限近期热点问题FQ 新手问题解答
  8. 关于CentOS7虚拟机出现Failed to start LSB: Bring up/down的解决方法
  9. PostgreSql 分页limit
  10. Eclipse优化设置技巧
  11. 操作必须使用一个可更新的查询
  12. 汇客huikeCRM项目实战-牛刀小试
  13. 前端取值的方式(ModelMap)
  14. mac如何打开php文件夹,苹果Mac系统怎么打开隐藏文件夹Library?_苹果MA
  15. 9.9 买礼物的艰辛 2719
  16. Windows共享Linux打印机,在Ubuntu系统中使用局域网内Windows共享打印机的方法
  17. 如何使用windows的计划任务?计划任务
  18. 为什么鸿蒙系统有摩尔纹,摩尔纹
  19. WARN [Consumer clientId=consumer-console-consumer-22243-1, groupId=console-consumer-22243] Bootstrap
  20. 产业互联网周报:钉钉被曝组织优化,涉及自研 SaaS、硬件部门;马斯克暂停Twitter收购;谷歌发布AlloyDB数据库服务...

热门文章

  1. learnpython3thehardway视频_LearnPython3theHardWay__Excercise 13 Parameters, Unpacking, Variables
  2. mysql 5.5 免安装_mysql 5.5.56免安装版配置方法
  3. 多重背包问题以及二进制优化
  4. Piggy-Bank POJ - 1384(完全背包+背包放满)
  5. 计算机连接拒绝访问,Win10系统下Windows无法连接到打印机,拒绝访问的解决办法...
  6. word List 11
  7. 数据结构----冒泡排序
  8. char *与char []
  9. Codeforces Round #588 (Div. 2) F. Konrad and Company Evaluation 图论 + 建反图 好题
  10. Rinne Loves Xor