字符数组输入流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)来代替实现。。。
protected char buf[]; 自带字符数组 protected int pos; buf中下一个要被读取的字符位置 protected int markedPos = 0; buf中被mark的字符下标 protected int count; 字符数组中总数、buf中索引为count和下一个都没有字符存在。
CharArrayReader(char buf[]); 使用传入的buf构造CharArrayReader CharArrayReader(char buf[], int offset, int length); 使用传入的buf的一部分构造CharArrayReader
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个字符、返回实际丢弃的字符个数
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; } }
字符数组输出流caw、用于将字符写入到内置字符缓存数组char[] buf中、当此数组存放满员时会自动扩容、同样与ByteArrayOutputStream相比他也提供了几个操作buf中字符的方法、可使用 toCharArray() 和 toString() 获取数据、还可使用writeTo(Writer out)将buf写入到底层流中。同样在此类上调用 close()、flush()无效,不会产生IOException、并且在关闭该流后仍然可以调用此类中的各个方法。
protected char buf[]; 用于存放写入CharArrayWriter的字符、存满自动扩容。 protected int count; buf中现有的字符数
public CharArrayWriter() 使用默认buf大小创建CharArrayWriter。 public CharArrayWriter(int initialSize) 使用指定的buf大小创建CharArrayWriter。
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)中
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() { } }
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时传入的字符数组)。