home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / sybase / starbuck / java.z / BufferedInputStream.java < prev    next >
Text File  |  1996-05-03  |  7KB  |  223 lines

  1. /*
  2.  * @(#)BufferedInputStream.java    1.21 95/12/18 Arthur van Hoff
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package java.io;
  21.  
  22. /**
  23.  * A buffered input stream. This stream lets you read in characters
  24.  * from a stream without causing a read every time. The data
  25.  * is read into a buffer, subsequent reads result in a fast
  26.  * buffer access.
  27.  *
  28.  * @version     1.21, 18 Dec 1995
  29.  * @author    Arthur van Hoff
  30.  */
  31. public
  32. class BufferedInputStream extends FilterInputStream {
  33.     /**
  34.      * The buffer where data is stored.
  35.      */
  36.     protected byte buf[];
  37.  
  38.     /**
  39.      * The number of bytes in the buffer.
  40.      */
  41.     protected int count;
  42.  
  43.     /**
  44.      * The current position in the buffer.
  45.      */
  46.     protected int pos;
  47.     
  48.     /**
  49.      * The position in the buffer of the current mark.  This mark is 
  50.      * set to -1 if there is no current mark.
  51.      */
  52.     protected int markpos = -1;
  53.  
  54.     /**
  55.      * The maximum readahead allowed after a mark() before
  56.      * subsequent calls to reset() fail.
  57.      */
  58.     protected int marklimit;
  59.  
  60.     /**
  61.      * Creates a new buffered stream with a default
  62.      * buffer size.
  63.      * @param in     the input stream
  64.      */
  65.     public BufferedInputStream(InputStream in) {
  66.     this(in, 2048);
  67.     }
  68.  
  69.     /**
  70.      * Creates a new buffered stream with the specified
  71.      * buffer size.
  72.      * @param in         the input stream
  73.      * @param size    the buffer size
  74.      */
  75.     public BufferedInputStream(InputStream in, int size) {
  76.     super(in);
  77.     buf = new byte[size];
  78.     }
  79.  
  80.     /**
  81.      * Fills the buffer with more data, taking into account
  82.      * shuffling and other tricks for dealing with marks.
  83.      * Assumes that it is being called by a synchronized method.
  84.      * This method also assumes that all data has already been read in,
  85.      * hence pos > count.
  86.      */
  87.     private void fill() throws IOException {
  88.     if (markpos < 0)
  89.         pos = 0;        /* no mark: throw away the buffer */
  90.     else if (pos >= buf.length)    /* no room left in buffer */
  91.         if (markpos > 0) {    /* can throw away early part of the buffer */
  92.         int sz = pos - markpos;
  93.         System.arraycopy(buf, markpos, buf, 0, sz);
  94.         pos = sz;
  95.         markpos = 0;
  96.         } else if (buf.length >= marklimit) {
  97.         markpos = -1;    /* buffer got too big, invalidate mark */
  98.         pos = 0;    /* drop buffer contents */
  99.         } else {        /* grow buffer */
  100.         int nsz = pos * 2;
  101.         if (nsz > marklimit)
  102.             nsz = marklimit;
  103.         byte nbuf[] = new byte[nsz];
  104.         System.arraycopy(buf, 0, nbuf, 0, pos);
  105.         buf = nbuf;
  106.         }
  107.     int n = in.read(buf, pos, buf.length - pos);
  108.     count = n <= 0 ? 0 : n + pos;
  109.     }
  110.  
  111.  
  112.     /**
  113.      * Reads a byte of data. This method will block if no input is 
  114.      * available.
  115.      * @return     the byte read, or -1 if the end of the
  116.      *        stream is reached.
  117.      * @exception IOException If an I/O error has occurred.
  118.      */
  119.     public synchronized int read() throws IOException {
  120.     if (pos >= count) {
  121.         fill();
  122.         if (count == 0)
  123.         return -1;
  124.     }
  125.     return buf[pos++] & 0xff;
  126.     }
  127.  
  128.     /**
  129.      * Reads into an array of bytes.
  130.      * Blocks until some input is available.
  131.      * @param b    the buffer into which the data is read
  132.      * @param off the start offset of the data
  133.      * @param len the maximum number of bytes read
  134.      * @return  the actual number of bytes read, -1 is
  135.      *         returned when the end of the stream is reached.
  136.      * @exception IOException If an I/O error has occurred.
  137.      */
  138.     public synchronized int read(byte b[], int off, int len) throws IOException {
  139.     int avail = count - pos;
  140.     if (avail <= 0) {
  141.         fill();
  142.         avail = count - pos;
  143.         if (avail <= 0)
  144.         return -1;
  145.     }
  146.     int cnt = (avail < len) ? avail : len;
  147.     System.arraycopy(buf, pos, b, off, cnt);
  148.     pos += cnt;
  149.     return cnt;
  150.     }
  151.  
  152.     /**
  153.      * Skips n bytes of input.
  154.      * @param n the number of bytes to be skipped
  155.      * @return    the actual number of bytes skipped.
  156.      * @exception IOException If an I/O error has occurred.
  157.      */
  158.     public synchronized long skip(long n) throws IOException {
  159.     long avail = count - pos;
  160.  
  161.     if (avail >= n) {
  162.         pos += n;
  163.         return n;
  164.     }
  165.  
  166.     pos += avail;
  167.     return avail + in.skip(n - avail);
  168.     }
  169.  
  170.     /**
  171.      * Returns the number of bytes that can be read
  172.      * without blocking. This total is the number
  173.      * of bytes in the buffer and the number of bytes
  174.      * available from the input stream.
  175.      * @return the number of available bytes.
  176.      */
  177.     public synchronized int available() throws IOException {
  178.     return (count - pos) + in.available();
  179.     }
  180.  
  181.     /**
  182.      * Marks the current position in the input stream.  A subsequent
  183.      * call to the reset() method will reposition the stream at the last
  184.      * marked position so that subsequent reads will re-read
  185.      * the same bytes.  The stream promises to allow readlimit bytes
  186.      * to be read before the mark position gets invalidated.
  187.      * @param readlimit the maximum limit of bytes allowed to be read before the 
  188.      * mark position becomes invalid.
  189.      */
  190.     public synchronized void mark(int readlimit) {
  191.     marklimit = readlimit;
  192.     markpos = pos;
  193.     }
  194.  
  195.     /**
  196.      * Repositions the stream to the last marked position.  If the
  197.      * stream has not been marked, or if the mark has been invalidated,
  198.      * an IOException is thrown.  Stream marks are intended to be used in
  199.      * situations where you need to read ahead a little to see what's in
  200.      * the stream.  Often this is most easily done by invoking some
  201.      * general parser.  If the stream is of the type handled by the
  202.      * parser, it just chugs along happily.  If the stream is not of
  203.      * that type, the parser should toss an exception when it fails.  If an exception
  204.      * gets tossed within readlimit bytes, the parser will allow the outer code to reset
  205.      * the stream and to try another parser.
  206.      * @exception IOException If the stream has not been marked or if the mark has been
  207.      * invalidated.
  208.      */
  209.     public synchronized void reset() throws IOException {
  210.     if (markpos < 0)
  211.         throw new IOException("Resetting to invalid mark");
  212.     pos = markpos;
  213.     }
  214.  
  215.     /**
  216.      * Returns a boolean indicating if this stream type supports 
  217.      * mark/reset.
  218.      */
  219.     public boolean markSupported() {
  220.     return true;
  221.     }
  222. }
  223.