Save This Page
Home » openjdk-7 » java » io » [javadoc | source]
    1   /*
    2    * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.io;
   27   
   28   
   29   /**
   30    * Reads text from a character-input stream, buffering characters so as to
   31    * provide for the efficient reading of characters, arrays, and lines.
   32    *
   33    * <p> The buffer size may be specified, or the default size may be used.  The
   34    * default is large enough for most purposes.
   35    *
   36    * <p> In general, each read request made of a Reader causes a corresponding
   37    * read request to be made of the underlying character or byte stream.  It is
   38    * therefore advisable to wrap a BufferedReader around any Reader whose read()
   39    * operations may be costly, such as FileReaders and InputStreamReaders.  For
   40    * example,
   41    *
   42    * <pre>
   43    * BufferedReader in
   44    *   = new BufferedReader(new FileReader("foo.in"));
   45    * </pre>
   46    *
   47    * will buffer the input from the specified file.  Without buffering, each
   48    * invocation of read() or readLine() could cause bytes to be read from the
   49    * file, converted into characters, and then returned, which can be very
   50    * inefficient.
   51    *
   52    * <p> Programs that use DataInputStreams for textual input can be localized by
   53    * replacing each DataInputStream with an appropriate BufferedReader.
   54    *
   55    * @see FileReader
   56    * @see InputStreamReader
   57    * @see java.nio.file.Files#newBufferedReader
   58    *
   59    * @author      Mark Reinhold
   60    * @since       JDK1.1
   61    */
   62   
   63   public class BufferedReader extends Reader {
   64   
   65       private Reader in;
   66   
   67       private char cb[];
   68       private int nChars, nextChar;
   69   
   70       private static final int INVALIDATED = -2;
   71       private static final int UNMARKED = -1;
   72       private int markedChar = UNMARKED;
   73       private int readAheadLimit = 0; /* Valid only when markedChar > 0 */
   74   
   75       /** If the next character is a line feed, skip it */
   76       private boolean skipLF = false;
   77   
   78       /** The skipLF flag when the mark was set */
   79       private boolean markedSkipLF = false;
   80   
   81       private static int defaultCharBufferSize = 8192;
   82       private static int defaultExpectedLineLength = 80;
   83   
   84       /**
   85        * Creates a buffering character-input stream that uses an input buffer of
   86        * the specified size.
   87        *
   88        * @param  in   A Reader
   89        * @param  sz   Input-buffer size
   90        *
   91        * @exception  IllegalArgumentException  If sz is <= 0
   92        */
   93       public BufferedReader(Reader in, int sz) {
   94           super(in);
   95           if (sz <= 0)
   96               throw new IllegalArgumentException("Buffer size <= 0");
   97           this.in = in;
   98           cb = new char[sz];
   99           nextChar = nChars = 0;
  100       }
  101   
  102       /**
  103        * Creates a buffering character-input stream that uses a default-sized
  104        * input buffer.
  105        *
  106        * @param  in   A Reader
  107        */
  108       public BufferedReader(Reader in) {
  109           this(in, defaultCharBufferSize);
  110       }
  111   
  112       /** Checks to make sure that the stream has not been closed */
  113       private void ensureOpen() throws IOException {
  114           if (in == null)
  115               throw new IOException("Stream closed");
  116       }
  117   
  118       /**
  119        * Fills the input buffer, taking the mark into account if it is valid.
  120        */
  121       private void fill() throws IOException {
  122           int dst;
  123           if (markedChar <= UNMARKED) {
  124               /* No mark */
  125               dst = 0;
  126           } else {
  127               /* Marked */
  128               int delta = nextChar - markedChar;
  129               if (delta >= readAheadLimit) {
  130                   /* Gone past read-ahead limit: Invalidate mark */
  131                   markedChar = INVALIDATED;
  132                   readAheadLimit = 0;
  133                   dst = 0;
  134               } else {
  135                   if (readAheadLimit <= cb.length) {
  136                       /* Shuffle in the current buffer */
  137                       System.arraycopy(cb, markedChar, cb, 0, delta);
  138                       markedChar = 0;
  139                       dst = delta;
  140                   } else {
  141                       /* Reallocate buffer to accommodate read-ahead limit */
  142                       char ncb[] = new char[readAheadLimit];
  143                       System.arraycopy(cb, markedChar, ncb, 0, delta);
  144                       cb = ncb;
  145                       markedChar = 0;
  146                       dst = delta;
  147                   }
  148                   nextChar = nChars = delta;
  149               }
  150           }
  151   
  152           int n;
  153           do {
  154               n = in.read(cb, dst, cb.length - dst);
  155           } while (n == 0);
  156           if (n > 0) {
  157               nChars = dst + n;
  158               nextChar = dst;
  159           }
  160       }
  161   
  162       /**
  163        * Reads a single character.
  164        *
  165        * @return The character read, as an integer in the range
  166        *         0 to 65535 (<tt>0x00-0xffff</tt>), or -1 if the
  167        *         end of the stream has been reached
  168        * @exception  IOException  If an I/O error occurs
  169        */
  170       public int read() throws IOException {
  171           synchronized (lock) {
  172               ensureOpen();
  173               for (;;) {
  174                   if (nextChar >= nChars) {
  175                       fill();
  176                       if (nextChar >= nChars)
  177                           return -1;
  178                   }
  179                   if (skipLF) {
  180                       skipLF = false;
  181                       if (cb[nextChar] == '\n') {
  182                           nextChar++;
  183                           continue;
  184                       }
  185                   }
  186                   return cb[nextChar++];
  187               }
  188           }
  189       }
  190   
  191       /**
  192        * Reads characters into a portion of an array, reading from the underlying
  193        * stream if necessary.
  194        */
  195       private int read1(char[] cbuf, int off, int len) throws IOException {
  196           if (nextChar >= nChars) {
  197               /* If the requested length is at least as large as the buffer, and
  198                  if there is no mark/reset activity, and if line feeds are not
  199                  being skipped, do not bother to copy the characters into the
  200                  local buffer.  In this way buffered streams will cascade
  201                  harmlessly. */
  202               if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {
  203                   return in.read(cbuf, off, len);
  204               }
  205               fill();
  206           }
  207           if (nextChar >= nChars) return -1;
  208           if (skipLF) {
  209               skipLF = false;
  210               if (cb[nextChar] == '\n') {
  211                   nextChar++;
  212                   if (nextChar >= nChars)
  213                       fill();
  214                   if (nextChar >= nChars)
  215                       return -1;
  216               }
  217           }
  218           int n = Math.min(len, nChars - nextChar);
  219           System.arraycopy(cb, nextChar, cbuf, off, n);
  220           nextChar += n;
  221           return n;
  222       }
  223   
  224       /**
  225        * Reads characters into a portion of an array.
  226        *
  227        * <p> This method implements the general contract of the corresponding
  228        * <code>{@link Reader#read(char[], int, int) read}</code> method of the
  229        * <code>{@link Reader}</code> class.  As an additional convenience, it
  230        * attempts to read as many characters as possible by repeatedly invoking
  231        * the <code>read</code> method of the underlying stream.  This iterated
  232        * <code>read</code> continues until one of the following conditions becomes
  233        * true: <ul>
  234        *
  235        *   <li> The specified number of characters have been read,
  236        *
  237        *   <li> The <code>read</code> method of the underlying stream returns
  238        *   <code>-1</code>, indicating end-of-file, or
  239        *
  240        *   <li> The <code>ready</code> method of the underlying stream
  241        *   returns <code>false</code>, indicating that further input requests
  242        *   would block.
  243        *
  244        * </ul> If the first <code>read</code> on the underlying stream returns
  245        * <code>-1</code> to indicate end-of-file then this method returns
  246        * <code>-1</code>.  Otherwise this method returns the number of characters
  247        * actually read.
  248        *
  249        * <p> Subclasses of this class are encouraged, but not required, to
  250        * attempt to read as many characters as possible in the same fashion.
  251        *
  252        * <p> Ordinarily this method takes characters from this stream's character
  253        * buffer, filling it from the underlying stream as necessary.  If,
  254        * however, the buffer is empty, the mark is not valid, and the requested
  255        * length is at least as large as the buffer, then this method will read
  256        * characters directly from the underlying stream into the given array.
  257        * Thus redundant <code>BufferedReader</code>s will not copy data
  258        * unnecessarily.
  259        *
  260        * @param      cbuf  Destination buffer
  261        * @param      off   Offset at which to start storing characters
  262        * @param      len   Maximum number of characters to read
  263        *
  264        * @return     The number of characters read, or -1 if the end of the
  265        *             stream has been reached
  266        *
  267        * @exception  IOException  If an I/O error occurs
  268        */
  269       public int read(char cbuf[], int off, int len) throws IOException {
  270           synchronized (lock) {
  271               ensureOpen();
  272               if ((off < 0) || (off > cbuf.length) || (len < 0) ||
  273                   ((off + len) > cbuf.length) || ((off + len) < 0)) {
  274                   throw new IndexOutOfBoundsException();
  275               } else if (len == 0) {
  276                   return 0;
  277               }
  278   
  279               int n = read1(cbuf, off, len);
  280               if (n <= 0) return n;
  281               while ((n < len) && in.ready()) {
  282                   int n1 = read1(cbuf, off + n, len - n);
  283                   if (n1 <= 0) break;
  284                   n += n1;
  285               }
  286               return n;
  287           }
  288       }
  289   
  290       /**
  291        * Reads a line of text.  A line is considered to be terminated by any one
  292        * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
  293        * followed immediately by a linefeed.
  294        *
  295        * @param      ignoreLF  If true, the next '\n' will be skipped
  296        *
  297        * @return     A String containing the contents of the line, not including
  298        *             any line-termination characters, or null if the end of the
  299        *             stream has been reached
  300        *
  301        * @see        java.io.LineNumberReader#readLine()
  302        *
  303        * @exception  IOException  If an I/O error occurs
  304        */
  305       String readLine(boolean ignoreLF) throws IOException {
  306           StringBuffer s = null;
  307           int startChar;
  308   
  309           synchronized (lock) {
  310               ensureOpen();
  311               boolean omitLF = ignoreLF || skipLF;
  312   
  313           bufferLoop:
  314               for (;;) {
  315   
  316                   if (nextChar >= nChars)
  317                       fill();
  318                   if (nextChar >= nChars) { /* EOF */
  319                       if (s != null && s.length() > 0)
  320                           return s.toString();
  321                       else
  322                           return null;
  323                   }
  324                   boolean eol = false;
  325                   char c = 0;
  326                   int i;
  327   
  328                   /* Skip a leftover '\n', if necessary */
  329                   if (omitLF && (cb[nextChar] == '\n'))
  330                       nextChar++;
  331                   skipLF = false;
  332                   omitLF = false;
  333   
  334               charLoop:
  335                   for (i = nextChar; i < nChars; i++) {
  336                       c = cb[i];
  337                       if ((c == '\n') || (c == '\r')) {
  338                           eol = true;
  339                           break charLoop;
  340                       }
  341                   }
  342   
  343                   startChar = nextChar;
  344                   nextChar = i;
  345   
  346                   if (eol) {
  347                       String str;
  348                       if (s == null) {
  349                           str = new String(cb, startChar, i - startChar);
  350                       } else {
  351                           s.append(cb, startChar, i - startChar);
  352                           str = s.toString();
  353                       }
  354                       nextChar++;
  355                       if (c == '\r') {
  356                           skipLF = true;
  357                       }
  358                       return str;
  359                   }
  360   
  361                   if (s == null)
  362                       s = new StringBuffer(defaultExpectedLineLength);
  363                   s.append(cb, startChar, i - startChar);
  364               }
  365           }
  366       }
  367   
  368       /**
  369        * Reads a line of text.  A line is considered to be terminated by any one
  370        * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
  371        * followed immediately by a linefeed.
  372        *
  373        * @return     A String containing the contents of the line, not including
  374        *             any line-termination characters, or null if the end of the
  375        *             stream has been reached
  376        *
  377        * @exception  IOException  If an I/O error occurs
  378        *
  379        * @see java.nio.file.Files#readAllLines
  380        */
  381       public String readLine() throws IOException {
  382           return readLine(false);
  383       }
  384   
  385       /**
  386        * Skips characters.
  387        *
  388        * @param  n  The number of characters to skip
  389        *
  390        * @return    The number of characters actually skipped
  391        *
  392        * @exception  IllegalArgumentException  If <code>n</code> is negative.
  393        * @exception  IOException  If an I/O error occurs
  394        */
  395       public long skip(long n) throws IOException {
  396           if (n < 0L) {
  397               throw new IllegalArgumentException("skip value is negative");
  398           }
  399           synchronized (lock) {
  400               ensureOpen();
  401               long r = n;
  402               while (r > 0) {
  403                   if (nextChar >= nChars)
  404                       fill();
  405                   if (nextChar >= nChars) /* EOF */
  406                       break;
  407                   if (skipLF) {
  408                       skipLF = false;
  409                       if (cb[nextChar] == '\n') {
  410                           nextChar++;
  411                       }
  412                   }
  413                   long d = nChars - nextChar;
  414                   if (r <= d) {
  415                       nextChar += r;
  416                       r = 0;
  417                       break;
  418                   }
  419                   else {
  420                       r -= d;
  421                       nextChar = nChars;
  422                   }
  423               }
  424               return n - r;
  425           }
  426       }
  427   
  428       /**
  429        * Tells whether this stream is ready to be read.  A buffered character
  430        * stream is ready if the buffer is not empty, or if the underlying
  431        * character stream is ready.
  432        *
  433        * @exception  IOException  If an I/O error occurs
  434        */
  435       public boolean ready() throws IOException {
  436           synchronized (lock) {
  437               ensureOpen();
  438   
  439               /*
  440                * If newline needs to be skipped and the next char to be read
  441                * is a newline character, then just skip it right away.
  442                */
  443               if (skipLF) {
  444                   /* Note that in.ready() will return true if and only if the next
  445                    * read on the stream will not block.
  446                    */
  447                   if (nextChar >= nChars && in.ready()) {
  448                       fill();
  449                   }
  450                   if (nextChar < nChars) {
  451                       if (cb[nextChar] == '\n')
  452                           nextChar++;
  453                       skipLF = false;
  454                   }
  455               }
  456               return (nextChar < nChars) || in.ready();
  457           }
  458       }
  459   
  460       /**
  461        * Tells whether this stream supports the mark() operation, which it does.
  462        */
  463       public boolean markSupported() {
  464           return true;
  465       }
  466   
  467       /**
  468        * Marks the present position in the stream.  Subsequent calls to reset()
  469        * will attempt to reposition the stream to this point.
  470        *
  471        * @param readAheadLimit   Limit on the number of characters that may be
  472        *                         read while still preserving the mark. An attempt
  473        *                         to reset the stream after reading characters
  474        *                         up to this limit or beyond may fail.
  475        *                         A limit value larger than the size of the input
  476        *                         buffer will cause a new buffer to be allocated
  477        *                         whose size is no smaller than limit.
  478        *                         Therefore large values should be used with care.
  479        *
  480        * @exception  IllegalArgumentException  If readAheadLimit is < 0
  481        * @exception  IOException  If an I/O error occurs
  482        */
  483       public void mark(int readAheadLimit) throws IOException {
  484           if (readAheadLimit < 0) {
  485               throw new IllegalArgumentException("Read-ahead limit < 0");
  486           }
  487           synchronized (lock) {
  488               ensureOpen();
  489               this.readAheadLimit = readAheadLimit;
  490               markedChar = nextChar;
  491               markedSkipLF = skipLF;
  492           }
  493       }
  494   
  495       /**
  496        * Resets the stream to the most recent mark.
  497        *
  498        * @exception  IOException  If the stream has never been marked,
  499        *                          or if the mark has been invalidated
  500        */
  501       public void reset() throws IOException {
  502           synchronized (lock) {
  503               ensureOpen();
  504               if (markedChar < 0)
  505                   throw new IOException((markedChar == INVALIDATED)
  506                                         ? "Mark invalid"
  507                                         : "Stream not marked");
  508               nextChar = markedChar;
  509               skipLF = markedSkipLF;
  510           }
  511       }
  512   
  513       public void close() throws IOException {
  514           synchronized (lock) {
  515               if (in == null)
  516                   return;
  517               in.close();
  518               in = null;
  519               cb = null;
  520           }
  521       }
  522   }

Save This Page
Home » openjdk-7 » java » io » [javadoc | source]