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

    1   /*
    2    * Copyright (c) 1994, 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    * A <code>PushbackInputStream</code> adds
   30    * functionality to another input stream, namely
   31    * the  ability to "push back" or "unread"
   32    * one byte. This is useful in situations where
   33    * it is  convenient for a fragment of code
   34    * to read an indefinite number of data bytes
   35    * that  are delimited by a particular byte
   36    * value; after reading the terminating byte,
   37    * the  code fragment can "unread" it, so that
   38    * the next read operation on the input stream
   39    * will reread the byte that was pushed back.
   40    * For example, bytes representing the  characters
   41    * constituting an identifier might be terminated
   42    * by a byte representing an  operator character;
   43    * a method whose job is to read just an identifier
   44    * can read until it  sees the operator and
   45    * then push the operator back to be re-read.
   46    *
   47    * @author  David Connelly
   48    * @author  Jonathan Payne
   49    * @since   JDK1.0
   50    */
   51   public
   52   class PushbackInputStream extends FilterInputStream {
   53       /**
   54        * The pushback buffer.
   55        * @since   JDK1.1
   56        */
   57       protected byte[] buf;
   58   
   59       /**
   60        * The position within the pushback buffer from which the next byte will
   61        * be read.  When the buffer is empty, <code>pos</code> is equal to
   62        * <code>buf.length</code>; when the buffer is full, <code>pos</code> is
   63        * equal to zero.
   64        *
   65        * @since   JDK1.1
   66        */
   67       protected int pos;
   68   
   69       /**
   70        * Check to make sure that this stream has not been closed
   71        */
   72       private void ensureOpen() throws IOException {
   73           if (in == null)
   74               throw new IOException("Stream closed");
   75       }
   76   
   77       /**
   78        * Creates a <code>PushbackInputStream</code>
   79        * with a pushback buffer of the specified <code>size</code>,
   80        * and saves its  argument, the input stream
   81        * <code>in</code>, for later use. Initially,
   82        * there is no pushed-back byte  (the field
   83        * <code>pushBack</code> is initialized to
   84        * <code>-1</code>).
   85        *
   86        * @param  in    the input stream from which bytes will be read.
   87        * @param  size  the size of the pushback buffer.
   88        * @exception IllegalArgumentException if size is <= 0
   89        * @since  JDK1.1
   90        */
   91       public PushbackInputStream(InputStream in, int size) {
   92           super(in);
   93           if (size <= 0) {
   94               throw new IllegalArgumentException("size <= 0");
   95           }
   96           this.buf = new byte[size];
   97           this.pos = size;
   98       }
   99   
  100       /**
  101        * Creates a <code>PushbackInputStream</code>
  102        * and saves its  argument, the input stream
  103        * <code>in</code>, for later use. Initially,
  104        * there is no pushed-back byte  (the field
  105        * <code>pushBack</code> is initialized to
  106        * <code>-1</code>).
  107        *
  108        * @param   in   the input stream from which bytes will be read.
  109        */
  110       public PushbackInputStream(InputStream in) {
  111           this(in, 1);
  112       }
  113   
  114       /**
  115        * Reads the next byte of data from this input stream. The value
  116        * byte is returned as an <code>int</code> in the range
  117        * <code>0</code> to <code>255</code>. If no byte is available
  118        * because the end of the stream has been reached, the value
  119        * <code>-1</code> is returned. This method blocks until input data
  120        * is available, the end of the stream is detected, or an exception
  121        * is thrown.
  122        *
  123        * <p> This method returns the most recently pushed-back byte, if there is
  124        * one, and otherwise calls the <code>read</code> method of its underlying
  125        * input stream and returns whatever value that method returns.
  126        *
  127        * @return     the next byte of data, or <code>-1</code> if the end of the
  128        *             stream has been reached.
  129        * @exception  IOException  if this input stream has been closed by
  130        *             invoking its {@link #close()} method,
  131        *             or an I/O error occurs.
  132        * @see        java.io.InputStream#read()
  133        */
  134       public int read() throws IOException {
  135           ensureOpen();
  136           if (pos < buf.length) {
  137               return buf[pos++] & 0xff;
  138           }
  139           return super.read();
  140       }
  141   
  142       /**
  143        * Reads up to <code>len</code> bytes of data from this input stream into
  144        * an array of bytes.  This method first reads any pushed-back bytes; after
  145        * that, if fewer than <code>len</code> bytes have been read then it
  146        * reads from the underlying input stream. If <code>len</code> is not zero, the method
  147        * blocks until at least 1 byte of input is available; otherwise, no
  148        * bytes are read and <code>0</code> is returned.
  149        *
  150        * @param      b     the buffer into which the data is read.
  151        * @param      off   the start offset in the destination array <code>b</code>
  152        * @param      len   the maximum number of bytes read.
  153        * @return     the total number of bytes read into the buffer, or
  154        *             <code>-1</code> if there is no more data because the end of
  155        *             the stream has been reached.
  156        * @exception  NullPointerException If <code>b</code> is <code>null</code>.
  157        * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
  158        * <code>len</code> is negative, or <code>len</code> is greater than
  159        * <code>b.length - off</code>
  160        * @exception  IOException  if this input stream has been closed by
  161        *             invoking its {@link #close()} method,
  162        *             or an I/O error occurs.
  163        * @see        java.io.InputStream#read(byte[], int, int)
  164        */
  165       public int read(byte[] b, int off, int len) throws IOException {
  166           ensureOpen();
  167           if (b == null) {
  168               throw new NullPointerException();
  169           } else if (off < 0 || len < 0 || len > b.length - off) {
  170               throw new IndexOutOfBoundsException();
  171           } else if (len == 0) {
  172               return 0;
  173           }
  174   
  175           int avail = buf.length - pos;
  176           if (avail > 0) {
  177               if (len < avail) {
  178                   avail = len;
  179               }
  180               System.arraycopy(buf, pos, b, off, avail);
  181               pos += avail;
  182               off += avail;
  183               len -= avail;
  184           }
  185           if (len > 0) {
  186               len = super.read(b, off, len);
  187               if (len == -1) {
  188                   return avail == 0 ? -1 : avail;
  189               }
  190               return avail + len;
  191           }
  192           return avail;
  193       }
  194   
  195       /**
  196        * Pushes back a byte by copying it to the front of the pushback buffer.
  197        * After this method returns, the next byte to be read will have the value
  198        * <code>(byte)b</code>.
  199        *
  200        * @param      b   the <code>int</code> value whose low-order
  201        *                  byte is to be pushed back.
  202        * @exception IOException If there is not enough room in the pushback
  203        *            buffer for the byte, or this input stream has been closed by
  204        *            invoking its {@link #close()} method.
  205        */
  206       public void unread(int b) throws IOException {
  207           ensureOpen();
  208           if (pos == 0) {
  209               throw new IOException("Push back buffer is full");
  210           }
  211           buf[--pos] = (byte)b;
  212       }
  213   
  214       /**
  215        * Pushes back a portion of an array of bytes by copying it to the front
  216        * of the pushback buffer.  After this method returns, the next byte to be
  217        * read will have the value <code>b[off]</code>, the byte after that will
  218        * have the value <code>b[off+1]</code>, and so forth.
  219        *
  220        * @param b the byte array to push back.
  221        * @param off the start offset of the data.
  222        * @param len the number of bytes to push back.
  223        * @exception IOException If there is not enough room in the pushback
  224        *            buffer for the specified number of bytes,
  225        *            or this input stream has been closed by
  226        *            invoking its {@link #close()} method.
  227        * @since     JDK1.1
  228        */
  229       public void unread(byte[] b, int off, int len) throws IOException {
  230           ensureOpen();
  231           if (len > pos) {
  232               throw new IOException("Push back buffer is full");
  233           }
  234           pos -= len;
  235           System.arraycopy(b, off, buf, pos, len);
  236       }
  237   
  238       /**
  239        * Pushes back an array of bytes by copying it to the front of the
  240        * pushback buffer.  After this method returns, the next byte to be read
  241        * will have the value <code>b[0]</code>, the byte after that will have the
  242        * value <code>b[1]</code>, and so forth.
  243        *
  244        * @param b the byte array to push back
  245        * @exception IOException If there is not enough room in the pushback
  246        *            buffer for the specified number of bytes,
  247        *            or this input stream has been closed by
  248        *            invoking its {@link #close()} method.
  249        * @since     JDK1.1
  250        */
  251       public void unread(byte[] b) throws IOException {
  252           unread(b, 0, b.length);
  253       }
  254   
  255       /**
  256        * Returns an estimate of the number of bytes that can be read (or
  257        * skipped over) from this input stream without blocking by the next
  258        * invocation of a method for this input stream. The next invocation might be
  259        * the same thread or another thread.  A single read or skip of this
  260        * many bytes will not block, but may read or skip fewer bytes.
  261        *
  262        * <p> The method returns the sum of the number of bytes that have been
  263        * pushed back and the value returned by {@link
  264        * java.io.FilterInputStream#available available}.
  265        *
  266        * @return     the number of bytes that can be read (or skipped over) from
  267        *             the input stream without blocking.
  268        * @exception  IOException  if this input stream has been closed by
  269        *             invoking its {@link #close()} method,
  270        *             or an I/O error occurs.
  271        * @see        java.io.FilterInputStream#in
  272        * @see        java.io.InputStream#available()
  273        */
  274       public int available() throws IOException {
  275           ensureOpen();
  276           int n = buf.length - pos;
  277           int avail = super.available();
  278           return n > (Integer.MAX_VALUE - avail)
  279                       ? Integer.MAX_VALUE
  280                       : n + avail;
  281       }
  282   
  283       /**
  284        * Skips over and discards <code>n</code> bytes of data from this
  285        * input stream. The <code>skip</code> method may, for a variety of
  286        * reasons, end up skipping over some smaller number of bytes,
  287        * possibly zero.  If <code>n</code> is negative, no bytes are skipped.
  288        *
  289        * <p> The <code>skip</code> method of <code>PushbackInputStream</code>
  290        * first skips over the bytes in the pushback buffer, if any.  It then
  291        * calls the <code>skip</code> method of the underlying input stream if
  292        * more bytes need to be skipped.  The actual number of bytes skipped
  293        * is returned.
  294        *
  295        * @param      n  {@inheritDoc}
  296        * @return     {@inheritDoc}
  297        * @exception  IOException  if the stream does not support seek,
  298        *            or the stream has been closed by
  299        *            invoking its {@link #close()} method,
  300        *            or an I/O error occurs.
  301        * @see        java.io.FilterInputStream#in
  302        * @see        java.io.InputStream#skip(long n)
  303        * @since      1.2
  304        */
  305       public long skip(long n) throws IOException {
  306           ensureOpen();
  307           if (n <= 0) {
  308               return 0;
  309           }
  310   
  311           long pskip = buf.length - pos;
  312           if (pskip > 0) {
  313               if (n < pskip) {
  314                   pskip = n;
  315               }
  316               pos += pskip;
  317               n -= pskip;
  318           }
  319           if (n > 0) {
  320               pskip += super.skip(n);
  321           }
  322           return pskip;
  323       }
  324   
  325       /**
  326        * Tests if this input stream supports the <code>mark</code> and
  327        * <code>reset</code> methods, which it does not.
  328        *
  329        * @return   <code>false</code>, since this class does not support the
  330        *           <code>mark</code> and <code>reset</code> methods.
  331        * @see     java.io.InputStream#mark(int)
  332        * @see     java.io.InputStream#reset()
  333        */
  334       public boolean markSupported() {
  335           return false;
  336       }
  337   
  338       /**
  339        * Marks the current position in this input stream.
  340        *
  341        * <p> The <code>mark</code> method of <code>PushbackInputStream</code>
  342        * does nothing.
  343        *
  344        * @param   readlimit   the maximum limit of bytes that can be read before
  345        *                      the mark position becomes invalid.
  346        * @see     java.io.InputStream#reset()
  347        */
  348       public synchronized void mark(int readlimit) {
  349       }
  350   
  351       /**
  352        * Repositions this stream to the position at the time the
  353        * <code>mark</code> method was last called on this input stream.
  354        *
  355        * <p> The method <code>reset</code> for class
  356        * <code>PushbackInputStream</code> does nothing except throw an
  357        * <code>IOException</code>.
  358        *
  359        * @exception  IOException  if this method is invoked.
  360        * @see     java.io.InputStream#mark(int)
  361        * @see     java.io.IOException
  362        */
  363       public synchronized void reset() throws IOException {
  364           throw new IOException("mark/reset not supported");
  365       }
  366   
  367       /**
  368        * Closes this input stream and releases any system resources
  369        * associated with the stream.
  370        * Once the stream has been closed, further read(), unread(),
  371        * available(), reset(), or skip() invocations will throw an IOException.
  372        * Closing a previously closed stream has no effect.
  373        *
  374        * @exception  IOException  if an I/O error occurs.
  375        */
  376       public synchronized void close() throws IOException {
  377           if (in == null)
  378               return;
  379           in.close();
  380           in = null;
  381           buf = null;
  382       }
  383   }

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