java io系列18之 CharArrayReader(字符數組輸入流)



從本章開始,我們開始對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         else
32             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 }
View Code

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 }
View Code

說明
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM