Chinaunix首页 | 论坛 | 博客
  • 博客访问: 757747
  • 博文数量: 130
  • 博客积分: 2951
  • 博客等级: 少校
  • 技术积分: 1875
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-04 18:32
文章分类

全部博文(130)

文章存档

2013年(1)

2012年(129)

分类: Java

2012-03-31 18:10:35

BufferedReader和BufferedInputStream类似,都是内部维护一个数组,先把底层的input读入到内部数组,再对内部数组进行各种操作。其重要的函数有


点击(此处)折叠或打开

  1. /**
  2.      * Creates a buffering character-input stream that uses an input buffer of
  3.      * the specified size.
  4.      * 
  5.      * @param in
  6.      * A Reader
  7.      * @param sz
  8.      * Input-buffer size
  9.      * 
  10.      * @exception IllegalArgumentException
  11.      * If sz is <= 0
  12.      */
  13.     public BufferedReader(Reader in, int sz) {
  14.         super(in);
  15.         if (sz <= 0)
  16.             throw new IllegalArgumentException("Buffer size <= 0");
  17.         this.in = in;
  18.         cb = new char[sz];
  19.         nextChar = nChars = 0; //nextChar代表下次要读取的位置,nChars表示总共的字符个数
  20.     }

点击(此处)折叠或打开

  1. /**
  2.      * Reads a single character.
  3.      * 
  4.      * @return The character read, as an integer in the range 0 to 65535 (
  5.      * 0x00-0xffff), or -1 if the end of the stream has been
  6.      * reached
  7.      * @exception IOException
  8.      * If an I/O error occurs
  9.      */
  10.     public int read() throws IOException {
  11.         synchronized (lock) {
  12.             ensureOpen();
  13.             for (;;) {
  14.                 if (nextChar >= nChars) {
  15.                     fill(); //如果要读取的位置已经超过最大的字符数,那么需要调用fill()读入新的数据
  16.                     if (nextChar >= nChars) //如果读完还是大于,那么说明其实之前就已经到了input的结尾,所以返回-1
  17.                         return -1;
  18.                 }
  19.                 if (skipLF) {
  20.                     skipLF = false;
  21.                     if (cb[nextChar] == '\n') {
  22.                         nextChar++;
  23.                         continue;
  24.                     }
  25.                 }
  26.                 return cb[nextChar++]; //返回当前位置的数据,并把nextChar位置加1
  27.             }
  28.         }
  29.     }

点击(此处)折叠或打开

  1. /**
  2.      * Fills the input buffer, taking the mark into account if it is valid.
  3.      */
  4.     private void fill() throws IOException {
  5.         int dst;
  6.         if (markedChar <= UNMARKED) {
  7.             /* No mark */
  8.             dst = 0;
  9.         } else {
  10.             /* Marked */
  11.             int delta = nextChar - markedChar;
  12.             if (delta >= readAheadLimit) {
  13.                 /* Gone past read-ahead limit: Invalidate mark */
  14.                 markedChar = INVALIDATED;
  15.                 readAheadLimit = 0;
  16.                 dst = 0;
  17.             } else {
  18.                 if (readAheadLimit <= cb.length) {
  19.                     /* Shuffle in the current buffer */
  20.                     System.arraycopy(cb, markedChar, cb, 0, delta);
  21.                     markedChar = 0;
  22.                     dst = delta;
  23.                 } else {
  24.                     /* Reallocate buffer to accommodate read-ahead limit */
  25.                     char ncb[] = new char[readAheadLimit];
  26.                     System.arraycopy(cb, markedChar, ncb, 0, delta);
  27.                     cb = ncb;
  28.                     markedChar = 0;
  29.                     dst = delta;
  30.                 }
  31.                 nextChar = nChars = delta;
  32.             }
  33.         }

  34.         int n;
  35.         do {
  36.             n = in.read(cb, dst, cb.length - dst); //从底层input读取数据到cb,cb中起始位置是dst, 读取的长度是cb的lenght减去起始位置dst
  37.         } while (n == 0);
  38.         if (n > 0) {
  39.             nChars = dst + n
  40.             nextChar = dst; //把起始位置赋给nextChar
  41.         }
  42.     }
与BufferedInputStream不同的是,BufferedReader有个ReadLine方法,可以读取整行数据,

点击(此处)折叠或打开
  1. String readLine(boolean ignoreLF) throws IOException {
  2.         StringBuffer s = null; //读取的数据最终放在这个s中,
  3.         int startChar;

  4.         synchronized (lock) {
  5.             ensureOpen();
  6.             boolean omitLF = ignoreLF || skipLF;

  7.             bufferLoop: for (;;) {

  8.                 if (nextChar >= nChars)
  9.                     fill();
  10.                 if (nextChar >= nChars) { /* EOF */
  11.                     if (s != null && s.length() > 0)
  12.                         return s.toString(); //从这里返回,可能是因为读取的数据最后没有以\n或\r结束
  13.                     else
  14.                         return null; //从这里返回,是因为开始读的时候,就已经是input的末尾了,所以s本身就没有被初始化,只能返回null
  15.                 }
  16.                 boolean eol = false;
  17.                 char c = 0;
  18.                 int i;

  19.                 /* Skip a leftover '\n', if necessary */
  20.                 if (omitLF && (cb[nextChar] == '\n'))
  21.                     nextChar++;
  22.                 skipLF = false;
  23.                 omitLF = false;

  24.                 charLoop: for (i = nextChar; i < nChars; i++) {
  25.                     c = cb[i];
  26.                     if ((c == '\n') || (c == '\r')) {
  27.                         eol = true; //读到\n或者\r,那么说明读到了行尾
  28.                         break charLoop;
  29.                     }
  30.                 }

  31.                 startChar = nextChar;
  32.                 nextChar = i;

  33.                 if (eol) {
  34.                     String str;
  35.                     if (s == null) {
  36.                         str = new String(cb, startChar, i - startChar); //运行到这,s为null,说明是第一次循环中就读到了行尾。
  37.                     } else {
  38.                         s.append(cb, startChar, i - startChar); //运行到这,起码说明是第二次循环了,s里已经有了第一次读取的数据
  39.                         str = s.toString();
  40.                     }
  41.                     nextChar++;
  42.                     if (c == '\r') {
  43.                         skipLF = true;
  44.                     }
  45.                     return str; //运行到这说明读到了行尾,返回str
  46.                 }

  47.                 if (s == null)
  48.                     s = new StringBuffer(defaultExpectedLineLength);
  49.                 s.append(cb, startChar, i - startChar); //运行到这说明,读取了整个cb的数据,发现一直没有\n或者\r, 之后回到最初循环继续读取。
  50.             }
  51.         }
  52.     }



有个问题,一直没搞懂 readAheadLimit 这个变量是干啥用的?


点击(此处)折叠或打开

  1. public class BufferedReader extends Reader {

  2.     private Reader in;

  3.     private char cb[];
  4.     private int nChars, nextChar;

  5.     private static final int INVALIDATED = -2;
  6.     private static final int UNMARKED = -1;
  7.     private int markedChar = UNMARKED;
  8.     private int readAheadLimit = 0; /* Valid only when markedChar > 0 */ ??????
  9. 。。。
  10. }

在mark函数中会设置它的值,在上面的fill()函数中会根据它的值来调整读取的数据多少和位置。

点击(此处)折叠或打开

  1. /**
  2.      * Marks the present position in the stream. Subsequent calls to reset()
  3.      * will attempt to reposition the stream to this point.
  4.      * 
  5.      * @param readAheadLimit
  6.      * Limit on the number of characters that may be read while still
  7.      * preserving the mark. An attempt to reset the stream after
  8.      * reading characters up to this limit or beyond may fail. A
  9.      * limit value larger than the size of the input buffer will
  10.      * cause a new buffer to be allocated whose size is no smaller
  11.      * than limit. Therefore large values should be used with care.
  12.      * 
  13.      * @exception IllegalArgumentException
  14.      * If readAheadLimit is < 0
  15.      * @exception IOException
  16.      * If an I/O error occurs
  17.      */
  18.     public void mark(int readAheadLimit) throws IOException {
  19.         if (readAheadLimit < 0) {
  20.             throw new IllegalArgumentException("Read-ahead limit < 0");
  21.         }
  22.         synchronized (lock) {
  23.             ensureOpen();
  24.             this.readAheadLimit = readAheadLimit;
  25.             markedChar = nextChar;
  26.             markedSkipLF = skipLF;
  27.         }
  28.     }


阅读(8014) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

☆彼岸★花开2012-04-02 07:00:49

这些都是底层的函数吗?看不懂哇~