java io系列18之 CharArrayReader(字符数组输入流)

来源:互联网 发布:时时彩源码2017论坛 编辑:程序博客网 时间:2024/05/21 01:46

从本章开始,我们开始对java io中的“字符流”进行学习。首先,要学习的是CharArrayReader。学习时,我们先对CharArrayReader有个大致了解,然后深入了解一下它的源码,最后通过示例来掌握它的用法。

转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_18.html

CharArrayReader 介绍

CharArrayReader 是字符数组输入流。它和ByteArrayInputStream类似,只不过ByteArrayInputStream是字节数组输入流,而CharArray是字符数组输入流。CharArrayReader 是用于读取字符数组,它继承于Reader。操作的数据是以字符为单位!


CharArrayReader 函数列表

复制代码
CharArrayReader(char[] buf)CharArrayReader(char[] buf, int offset, int length)void      close()void      mark(int readLimit)boolean   markSupported()int       read()int       read(char[] buffer, int offset, int len)boolean   ready()void      reset()long      skip(long charCount)
复制代码

 

Reader和CharArrayReader源码分析

Reader是CharArrayReader的父类,我们先看看Reader的源码,然后再学CharArrayReader的源码。

1. Reader源码分析(基于jdk1.7.40)

复制代码
 1 package java.io; 2  3 public abstract class Reader implements Readable, Closeable { 4  5     protected Object lock; 6  7     protected Reader() { 8         this.lock = this; 9     }10 11     protected Reader(Object lock) {12         if (lock == null) {13             throw new NullPointerException();14         }15         this.lock = lock;16     }17 18     public int read(java.nio.CharBuffer target) throws IOException {19         int len = target.remaining();20         char[] cbuf = new char[len];21         int n = read(cbuf, 0, len);22         if (n > 0)23             target.put(cbuf, 0, n);24         return n;25     }26 27     public int read() throws IOException {28         char cb[] = new char[1];29         if (read(cb, 0, 1) == -1)30             return -1;31         else32             return cb[0];33     }34 35     public int read(char cbuf[]) throws IOException {36         return read(cbuf, 0, cbuf.length);37     }38 39     abstract public int read(char cbuf[], int off, int len) throws IOException;40 41     private static final int maxSkipBufferSize = 8192;42 43     private char skipBuffer[] = null;44 45     public long skip(long n) throws IOException {46         if (n < 0L)47             throw new IllegalArgumentException("skip value is negative");48         int nn = (int) Math.min(n, maxSkipBufferSize);49         synchronized (lock) {50             if ((skipBuffer == null) || (skipBuffer.length < nn))51                 skipBuffer = new char[nn];52             long r = n;53             while (r > 0) {54                 int nc = read(skipBuffer, 0, (int)Math.min(r, nn));55                 if (nc == -1)56                     break;57                 r -= nc;58             }59             return n - r;60         }61     }62 63     public boolean ready() throws IOException {64         return false;65     }66 67     public boolean markSupported() {68         return false;69     }70 71     public void mark(int readAheadLimit) throws IOException {72         throw new IOException("mark() not supported");73     }74 75     public void reset() throws IOException {76         throw new IOException("reset() not supported");77     }78 79      abstract public void close() throws IOException;80 }
复制代码

2. CharArrayReader 源码分析(基于jdk1.7.40)

复制代码
  1 package java.io;  2   3 public class CharArrayReader extends Reader {  4     // 字符数组缓冲  5     protected char buf[];  6   7     // 下一个被获取的字符的位置  8     protected int pos;  9  10     // 被标记的位置 11     protected int markedPos = 0; 12  13     // 字符缓冲的长度 14     protected int count; 15  16     // 构造函数 17     public CharArrayReader(char buf[]) { 18         this.buf = buf; 19         this.pos = 0; 20         this.count = buf.length; 21     } 22  23     // 构造函数 24     public CharArrayReader(char buf[], int offset, int length) { 25         if ((offset < 0) || (offset > buf.length) || (length < 0) || 26             ((offset + length) < 0)) { 27             throw new IllegalArgumentException(); 28         } 29         this.buf = buf; 30         this.pos = offset; 31         this.count = Math.min(offset + length, buf.length); 32         this.markedPos = offset; 33     } 34  35     // 判断“CharArrayReader是否有效”。 36     // 若字符缓冲为null,则认为其无效。 37     private void ensureOpen() throws IOException { 38         if (buf == null) 39             throw new IOException("Stream closed"); 40     } 41  42     // 读取下一个字符。即返回字符缓冲区中下一位置的值。 43     // 注意:读取的是字符! 44     public int read() throws IOException { 45         synchronized (lock) { 46             ensureOpen(); 47             if (pos >= count) 48                 return -1; 49             else 50                 return buf[pos++]; 51         } 52     } 53  54     // 读取数据,并保存到字符数组b中从off开始的位置中,len是读取长度。 55     public int read(char b[], int off, int len) throws IOException { 56         synchronized (lock) { 57             ensureOpen(); 58             if ((off < 0) || (off > b.length) || (len < 0) || 59                 ((off + len) > b.length) || ((off + len) < 0)) { 60                 throw new IndexOutOfBoundsException(); 61             } else if (len == 0) { 62                 return 0; 63             } 64  65             if (pos >= count) { 66                 return -1; 67             } 68             if (pos + len > count) { 69                 len = count - pos; 70             } 71             if (len <= 0) { 72                 return 0; 73             } 74             System.arraycopy(buf, pos, b, off, len); 75             pos += len; 76             return len; 77         } 78     } 79  80     // 跳过n个字符 81     public long skip(long n) throws IOException { 82         synchronized (lock) { 83             ensureOpen(); 84             if (pos + n > count) { 85                 n = count - pos; 86             } 87             if (n < 0) { 88                 return 0; 89             } 90             pos += n; 91             return n; 92         } 93     } 94  95     // 判断“是否能读取下一个字符”。能的话,返回true。 96     public boolean ready() throws IOException { 97         synchronized (lock) { 98             ensureOpen(); 99             return (count - pos) > 0;100         }101     }102 103     public boolean markSupported() {104         return true;105     }106 107     // 保存当前位置。readAheadLimit在此处没有任何实际意义108     // mark()必须和reset()配合使用才有意义!109     public void mark(int readAheadLimit) throws IOException {110         synchronized (lock) {111             ensureOpen();112             markedPos = pos;113         }114     }115 116     // 重置“下一个读取位置”为“mark所标记的位置”117     public void reset() throws IOException {118         synchronized (lock) {119             ensureOpen();120             pos = markedPos;121         }122     }123 124     public void close() {125         buf = null;126     }127 }
复制代码

说明
CharArrayReader实际上是通过“字符数组”去保存数据。

(01) 通过 CharArrayReader(char[] buf) 或 CharArrayReader(char[] buf, int offset, int length) ,我们可以根据buf数组来创建CharArrayReader对象。
(02) read()的作用是从CharArrayReader中“读取下一个字符”。
(03) read(char[] buffer, int offset, int len)的作用是从CharArrayReader读取字符数据,并写入到字符数组buffer中。offset是将字符写入到buffer的起始位置,len是写入的字符的长度。
(04) markSupported()是判断CharArrayReader是否支持“标记功能”。它始终返回true。
(05) mark(int readlimit)的作用是记录标记位置。记录标记位置之后,某一时刻调用reset()则将“CharArrayReader下一个被读取的位置”重置到“mark(int readlimit)所标记的位置”;也就是说,reset()之后再读取CharArrayReader时,是从mark(int readlimit)所标记的位置开始读取。

 

示例代码

关于CharArrayReader中API的详细用法,参考示例代码(CharArrayReaderTest.java): 

复制代码
 1 /** 2  * CharArrayReader 演示程序 3  * 4  * @author skywang 5  */ 6  7 import java.io.CharArrayReader; 8 import java.io.CharArrayWriter; 9 import java.io.IOException;10 11 public class CharArrayReaderTest {12 13     private static final int LEN = 5;14     // 对应英文字母“abcdefghijklmnopqrstuvwxyz”15     private static final char[] ArrayLetters = new char[] {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};16     17     public static void main(String[] args) {18         tesCharArrayReader() ;19     }20 21     /**22      * CharArrayReader的API测试函数23      */24     private static void tesCharArrayReader() {25         try {26             // 创建CharArrayReader字符流,内容是ArrayLetters数组27             CharArrayReader car = new CharArrayReader(ArrayLetters);28 29             // 从字符数组流中读取5个字符30             for (int i=0; i<LEN; i++) {31                 // 若能继续读取下一个字符,则读取下一个字符32                 if (car.ready() == true) {33                     // 读取“字符流的下一个字符”34                     char tmp = (char)car.read();35                     System.out.printf("%d : %c\n", i, tmp);36                 }37             }38 39             // 若“该字符流”不支持标记功能,则直接退出40             if (!car.markSupported()) {41                 System.out.println("make not supported!");42                 return ;43             }44 45             // 标记“字符流中下一个被读取的位置”。即--标记“f”,因为因为前面已经读取了5个字符,所以下一个被读取的位置是第6个字符”46             // (01), CharArrayReader类的mark(0)函数中的“参数0”是没有实际意义的。47             // (02), mark()与reset()是配套的,reset()会将“字符流中下一个被读取的位置”重置为“mark()中所保存的位置”48             car.mark(0);49 50             // 跳过5个字符。跳过5个字符后,字符流中下一个被读取的值应该是“k”。51             car.skip(5);52 53             // 从字符流中读取5个数据。即读取“klmno”54             char[] buf = new char[LEN];55             car.read(buf, 0, LEN);56             System.out.printf("buf=%s\n", String.valueOf(buf));57         58             // 重置“字符流”:即,将“字符流中下一个被读取的位置”重置到“mark()所标记的位置”,即f。59             car.reset();60             // 从“重置后的字符流”中读取5个字符到buf中。即读取“fghij”61             car.read(buf, 0, LEN);62             System.out.printf("buf=%s\n", String.valueOf(buf));63         } catch (IOException e) {64             e.printStackTrace();65         }66     }67 }
复制代码

运行结果

0 : a
1 : b
2 : c
3 : d
4 : e
buf=klmno
buf=fghij

0 0
原创粉丝点击