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

    1   /*
    2    * Copyright (c) 1996, 2006, 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    * A buffered character-input stream that keeps track of line numbers.  This
   31    * class defines methods {@link #setLineNumber(int)} and {@link
   32    * #getLineNumber()} for setting and getting the current line number
   33    * respectively.
   34    *
   35    * <p> By default, line numbering begins at 0. This number increments at every
   36    * <a href="#lt">line terminator</a> as the data is read, and can be changed
   37    * with a call to <tt>setLineNumber(int)</tt>.  Note however, that
   38    * <tt>setLineNumber(int)</tt> does not actually change the current position in
   39    * the stream; it only changes the value that will be returned by
   40    * <tt>getLineNumber()</tt>.
   41    *
   42    * <p> A line is considered to be <a name="lt">terminated</a> by any one of a
   43    * line feed ('\n'), a carriage return ('\r'), or a carriage return followed
   44    * immediately by a linefeed.
   45    *
   46    * @author      Mark Reinhold
   47    * @since       JDK1.1
   48    */
   49   
   50   public class LineNumberReader extends BufferedReader {
   51   
   52       /** The current line number */
   53       private int lineNumber = 0;
   54   
   55       /** The line number of the mark, if any */
   56       private int markedLineNumber; // Defaults to 0
   57   
   58       /** If the next character is a line feed, skip it */
   59       private boolean skipLF;
   60   
   61       /** The skipLF flag when the mark was set */
   62       private boolean markedSkipLF;
   63   
   64       /**
   65        * Create a new line-numbering reader, using the default input-buffer
   66        * size.
   67        *
   68        * @param  in
   69        *         A Reader object to provide the underlying stream
   70        */
   71       public LineNumberReader(Reader in) {
   72           super(in);
   73       }
   74   
   75       /**
   76        * Create a new line-numbering reader, reading characters into a buffer of
   77        * the given size.
   78        *
   79        * @param  in
   80        *         A Reader object to provide the underlying stream
   81        *
   82        * @param  sz
   83        *         An int specifying the size of the buffer
   84        */
   85       public LineNumberReader(Reader in, int sz) {
   86           super(in, sz);
   87       }
   88   
   89       /**
   90        * Set the current line number.
   91        *
   92        * @param  lineNumber
   93        *         An int specifying the line number
   94        *
   95        * @see #getLineNumber
   96        */
   97       public void setLineNumber(int lineNumber) {
   98           this.lineNumber = lineNumber;
   99       }
  100   
  101       /**
  102        * Get the current line number.
  103        *
  104        * @return  The current line number
  105        *
  106        * @see #setLineNumber
  107        */
  108       public int getLineNumber() {
  109           return lineNumber;
  110       }
  111   
  112       /**
  113        * Read a single character.  <a href="#lt">Line terminators</a> are
  114        * compressed into single newline ('\n') characters.  Whenever a line
  115        * terminator is read the current line number is incremented.
  116        *
  117        * @return  The character read, or -1 if the end of the stream has been
  118        *          reached
  119        *
  120        * @throws  IOException
  121        *          If an I/O error occurs
  122        */
  123       public int read() throws IOException {
  124           synchronized (lock) {
  125               int c = super.read();
  126               if (skipLF) {
  127                   if (c == '\n')
  128                       c = super.read();
  129                   skipLF = false;
  130               }
  131               switch (c) {
  132               case '\r':
  133                   skipLF = true;
  134               case '\n':          /* Fall through */
  135                   lineNumber++;
  136                   return '\n';
  137               }
  138               return c;
  139           }
  140       }
  141   
  142       /**
  143        * Read characters into a portion of an array.  Whenever a <a
  144        * href="#lt">line terminator</a> is read the current line number is
  145        * incremented.
  146        *
  147        * @param  cbuf
  148        *         Destination buffer
  149        *
  150        * @param  off
  151        *         Offset at which to start storing characters
  152        *
  153        * @param  len
  154        *         Maximum number of characters to read
  155        *
  156        * @return  The number of bytes read, or -1 if the end of the stream has
  157        *          already been reached
  158        *
  159        * @throws  IOException
  160        *          If an I/O error occurs
  161        */
  162       public int read(char cbuf[], int off, int len) throws IOException {
  163           synchronized (lock) {
  164               int n = super.read(cbuf, off, len);
  165   
  166               for (int i = off; i < off + n; i++) {
  167                   int c = cbuf[i];
  168                   if (skipLF) {
  169                       skipLF = false;
  170                       if (c == '\n')
  171                           continue;
  172                   }
  173                   switch (c) {
  174                   case '\r':
  175                       skipLF = true;
  176                   case '\n':      /* Fall through */
  177                       lineNumber++;
  178                       break;
  179                   }
  180               }
  181   
  182               return n;
  183           }
  184       }
  185   
  186       /**
  187        * Read a line of text.  Whenever a <a href="#lt">line terminator</a> is
  188        * read the current line number is incremented.
  189        *
  190        * @return  A String containing the contents of the line, not including
  191        *          any <a href="#lt">line termination characters</a>, or
  192        *          <tt>null</tt> if the end of the stream has been reached
  193        *
  194        * @throws  IOException
  195        *          If an I/O error occurs
  196        */
  197       public String readLine() throws IOException {
  198           synchronized (lock) {
  199               String l = super.readLine(skipLF);
  200               skipLF = false;
  201               if (l != null)
  202                   lineNumber++;
  203               return l;
  204           }
  205       }
  206   
  207       /** Maximum skip-buffer size */
  208       private static final int maxSkipBufferSize = 8192;
  209   
  210       /** Skip buffer, null until allocated */
  211       private char skipBuffer[] = null;
  212   
  213       /**
  214        * Skip characters.
  215        *
  216        * @param  n
  217        *         The number of characters to skip
  218        *
  219        * @return  The number of characters actually skipped
  220        *
  221        * @throws  IOException
  222        *          If an I/O error occurs
  223        *
  224        * @throws  IllegalArgumentException
  225        *          If <tt>n</tt> is negative
  226        */
  227       public long skip(long n) throws IOException {
  228           if (n < 0)
  229               throw new IllegalArgumentException("skip() value is negative");
  230           int nn = (int) Math.min(n, maxSkipBufferSize);
  231           synchronized (lock) {
  232               if ((skipBuffer == null) || (skipBuffer.length < nn))
  233                   skipBuffer = new char[nn];
  234               long r = n;
  235               while (r > 0) {
  236                   int nc = read(skipBuffer, 0, (int) Math.min(r, nn));
  237                   if (nc == -1)
  238                       break;
  239                   r -= nc;
  240               }
  241               return n - r;
  242           }
  243       }
  244   
  245       /**
  246        * Mark the present position in the stream.  Subsequent calls to reset()
  247        * will attempt to reposition the stream to this point, and will also reset
  248        * the line number appropriately.
  249        *
  250        * @param  readAheadLimit
  251        *         Limit on the number of characters that may be read while still
  252        *         preserving the mark.  After reading this many characters,
  253        *         attempting to reset the stream may fail.
  254        *
  255        * @throws  IOException
  256        *          If an I/O error occurs
  257        */
  258       public void mark(int readAheadLimit) throws IOException {
  259           synchronized (lock) {
  260               super.mark(readAheadLimit);
  261               markedLineNumber = lineNumber;
  262               markedSkipLF     = skipLF;
  263           }
  264       }
  265   
  266       /**
  267        * Reset the stream to the most recent mark.
  268        *
  269        * @throws  IOException
  270        *          If the stream has not been marked, or if the mark has been
  271        *          invalidated
  272        */
  273       public void reset() throws IOException {
  274           synchronized (lock) {
  275               super.reset();
  276               lineNumber = markedLineNumber;
  277               skipLF     = markedSkipLF;
  278           }
  279       }
  280   
  281   }

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