home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / BufferedInputStream.java < prev    next >
Text File  |  1997-05-21  |  13KB  |  336 lines

  1. /*
  2.  * @(#)BufferedInputStream.java    1.26 97/03/03
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22.  
  23. package java.io;
  24.  
  25. /**
  26.  * The class implements a buffered input stream. By setting up such 
  27.  * an input stream, an application can read bytes from a stream 
  28.  * without necessarily causing a call to the underlying system for 
  29.  * each byte read. The data is read by blocks into a buffer; 
  30.  * subsequent reads can access the data directly from the buffer. 
  31.  *
  32.  * @author  Arthur van Hoff
  33.  * @version 1.26, 03/03/97
  34.  * @since   JDK1.0
  35.  */
  36. public
  37. class BufferedInputStream extends FilterInputStream {
  38.     /**
  39.      * The buffer where data is stored. 
  40.      *
  41.      * @since   JDK1.0
  42.      */
  43.     protected byte buf[];
  44.  
  45.     /**
  46.      * The index one greater than the index of the last valid byte in 
  47.      * the buffer. 
  48.      *
  49.      * @since   JDK1.0
  50.      */
  51.     protected int count;
  52.  
  53.     /**
  54.      * The current position in the buffer. This is the index of the next 
  55.      * character to be read from the <code>buf</code> array. 
  56.      *
  57.      * @see     java.io.BufferedInputStream#buf
  58.      * @since   JDK1.0
  59.      */
  60.     protected int pos;
  61.     
  62.     /**
  63.      * The value of the <code>pos</code> field at the time the last 
  64.      * <code>mark</code> method was called. The value of this field is 
  65.      * <code>-1</code> if there is no current mark. 
  66.      *
  67.      * @see     java.io.BufferedInputStream#mark(int)
  68.      * @see     java.io.BufferedInputStream#pos
  69.      * @since   JDK1.0
  70.      */
  71.     protected int markpos = -1;
  72.  
  73.     /**
  74.      * The maximum read ahead allowed after a call to the 
  75.      * <code>mark</code> method before subsequent calls to the 
  76.      * <code>reset</code> method fail. 
  77.      *
  78.      * @see     java.io.BufferedInputStream#mark(int)
  79.      * @see     java.io.BufferedInputStream#reset()
  80.      * @since   JDK1.0
  81.      */
  82.     protected int marklimit;
  83.  
  84.     /**
  85.      * Creates a new buffered input stream to read data from the 
  86.      * specified input stream with a default 512-byte buffer size. 
  87.      *
  88.      * @param   in   the underlying input stream.
  89.      * @since   JDK1.0
  90.      */
  91.     public BufferedInputStream(InputStream in) {
  92.     this(in, 2048);
  93.     }
  94.  
  95.     /**
  96.      * Creates a new buffered input stream to read data from the 
  97.      * specified input stream with the specified buffer size. 
  98.      *
  99.      * @param   in     the underlying input stream.
  100.      * @param   size   the buffer size.
  101.      * @since   JDK1.0
  102.      */
  103.     public BufferedInputStream(InputStream in, int size) {
  104.     super(in);
  105.     buf = new byte[size];
  106.     }
  107.  
  108.     /**
  109.      * Fills the buffer with more data, taking into account
  110.      * shuffling and other tricks for dealing with marks.
  111.      * Assumes that it is being called by a synchronized method.
  112.      * This method also assumes that all data has already been read in,
  113.      * hence pos > count.
  114.      */
  115.     private void fill() throws IOException {
  116.     if (markpos < 0)
  117.         pos = 0;        /* no mark: throw away the buffer */
  118.     else if (pos >= buf.length)    /* no room left in buffer */
  119.         if (markpos > 0) {    /* can throw away early part of the buffer */
  120.         int sz = pos - markpos;
  121.         System.arraycopy(buf, markpos, buf, 0, sz);
  122.         pos = sz;
  123.         markpos = 0;
  124.         } else if (buf.length >= marklimit) {
  125.         markpos = -1;    /* buffer got too big, invalidate mark */
  126.         pos = 0;    /* drop buffer contents */
  127.         } else {        /* grow buffer */
  128.         int nsz = pos * 2;
  129.         if (nsz > marklimit)
  130.             nsz = marklimit;
  131.         byte nbuf[] = new byte[nsz];
  132.         System.arraycopy(buf, 0, nbuf, 0, pos);
  133.         buf = nbuf;
  134.         }
  135.     int n = in.read(buf, pos, buf.length - pos);
  136.     count = n <= 0 ? pos : n + pos;
  137.     }
  138.  
  139.     /**
  140.      * Reads the next byte of data from this buffered input stream. The 
  141.      * value byte is returned as an <code>int</code> in the range 
  142.      * <code>0</code> to <code>255</code>. If no byte is available 
  143.      * because the end of the stream has been reached, the value 
  144.      * <code>-1</code> is returned. This method blocks until input data 
  145.      * is available, the end of the stream is detected, or an exception 
  146.      * is thrown. 
  147.      * <p>
  148.      * The <code>read</code> method of <code>BufferedInputStream</code> 
  149.      * returns the next byte of data from its buffer if the buffer is not 
  150.      * empty. Otherwise, it refills the buffer from the underlying input 
  151.      * stream and returns the next character, if the underlying stream 
  152.      * has not returned an end-of-stream indicator. 
  153.      *
  154.      * @return     the next byte of data, or <code>-1</code> if the end of the
  155.      *             stream is reached.
  156.      * @exception  IOException  if an I/O error occurs.
  157.      * @see        java.io.FilterInputStream#in
  158.      * @since      JDK1.0
  159.      */
  160.     public synchronized int read() throws IOException {
  161.     if (pos >= count) {
  162.         fill();
  163.         if (pos >= count)
  164.         return -1;
  165.     }
  166.     return buf[pos++] & 0xff;
  167.     }
  168.  
  169.     /**
  170.      * Reads bytes into a portion of an array.  This method will block until
  171.      * some input is available, an I/O error occurs, or the end of the stream
  172.      * is reached.
  173.      *
  174.      * <p> If this stream's buffer is not empty, bytes are copied from it into
  175.      * the array argument.  Otherwise, the buffer is refilled from the
  176.      * underlying input stream and, unless the stream returns an end-of-stream
  177.      * indication, the array argument is filled with characters from the
  178.      * newly-filled buffer.
  179.      *
  180.      * <p> As an optimization, if the buffer is empty, the mark is not valid,
  181.      * and <code>len</code> is at least as large as the buffer, then this
  182.      * method will read directly from the underlying stream into the given
  183.      * array.  Thus redundant <code>BufferedInputStream</code>s will not copy
  184.      * data unnecessarily.
  185.      *
  186.      * @param      b     destination buffer.
  187.      * @param      off   offset at which to start storing bytes.
  188.      * @param      len   maximum number of bytes to read.
  189.      * @return     the number of bytes read, or <code>-1</code> if the end of
  190.      *             the stream has been reached.
  191.      * @exception  IOException  if an I/O error occurs.
  192.      */
  193.     public synchronized int read(byte b[], int off, int len) throws IOException {
  194.     int avail = count - pos;
  195.     if (avail <= 0) {
  196.         /* If the requested length is larger than the buffer, and if there
  197.            is no mark/reset activity, do not bother to copy the bytes into
  198.            the local buffer.  In this way buffered streams will cascade
  199.            harmlessly. */
  200.         if (len >= buf.length && markpos < 0) {
  201.         return in.read(b, off, len);
  202.         }
  203.         fill();
  204.         avail = count - pos;
  205.         if (avail <= 0)
  206.         return -1;
  207.     }
  208.     int cnt = (avail < len) ? avail : len;
  209.     System.arraycopy(buf, pos, b, off, cnt);
  210.     pos += cnt;
  211.     return cnt;
  212.     }
  213.  
  214.     /**
  215.      * Skips over and discards <code>n</code> bytes of data from the 
  216.      * input stream. The <code>skip</code> method may, for a variety of 
  217.      * reasons, end up skipping over some smaller number of bytes, 
  218.      * possibly zero. The actual number of bytes skipped is returned. 
  219.      * <p>
  220.      * The <code>skip</code> method of <code>BufferedInputStream</code> 
  221.      * compares the number of bytes it has available in its buffer, 
  222.      * <i>k</i>, where <i>k</i> = <code>count - pos</code>, 
  223.      * with <code>n</code>. If <code>n</code> ≤ <i>k</i>, 
  224.      * then the <code>pos</code> field is incremented by <code>n</code>. 
  225.      * Otherwise, the <code>pos</code> field is incremented to have the 
  226.      * value <code>count</code>, and the remaining bytes are skipped by 
  227.      * calling the <code>skip</code> method on the underlying input 
  228.      * stream, supplying the argument <code>n -</code> <i>k</i>. 
  229.      *
  230.      * @param      n   the number of bytes to be skipped.
  231.      * @return     the actual number of bytes skipped.
  232.      * @exception  IOException  if an I/O error occurs.
  233.      * @since      JDK1.0
  234.      */
  235.     public synchronized long skip(long n) throws IOException {
  236.     if (n < 0) {
  237.         return 0;
  238.     }
  239.     long avail = count - pos;
  240.  
  241.     if (avail >= n) {
  242. //__SYMC__
  243.         pos += (int)n;
  244. //        pos += n;
  245. //__SYMC__
  246.         return n;
  247.     }
  248.  
  249.     pos += avail;
  250.     return avail + in.skip(n - avail);
  251.     }
  252.  
  253.     /**
  254.      * Returns the number of bytes that can be read from this input 
  255.      * stream without blocking. 
  256.      * <p>
  257.      * The <code>available</code> method of 
  258.      * <code>BufferedInputStream</code> returns the sum of the the number 
  259.      * of bytes remaining to be read in the buffer 
  260.      * (<code>count - pos</code>) 
  261.      * and the result of calling the <code>available</code> method of the 
  262.      * underlying input stream. 
  263.      *
  264.      * @return     the number of bytes that can be read from this input
  265.      *             stream without blocking.
  266.      * @exception  IOException  if an I/O error occurs.
  267.      * @see        java.io.FilterInputStream#in
  268.      * @since      JDK1.0
  269.      */
  270.     public synchronized int available() throws IOException {
  271.     return (count - pos) + in.available();
  272.     }
  273.  
  274.     /**
  275.      * Marks the current position in this input stream. A subsequent 
  276.      * call to the <code>reset</code> method repositions the stream at 
  277.      * the last marked position so that subsequent reads re-read the same 
  278.      * bytes. 
  279.      * <p>
  280.      * The <code>readlimit</code> argument tells the input stream to 
  281.      * allow that many bytes to be read before the mark position gets 
  282.      * invalidated. 
  283.      *
  284.      * @param   readlimit   the maximum limit of bytes that can be read before
  285.      *                      the mark position becomes invalid.
  286.      * @see     java.io.BufferedInputStream#reset()
  287.      * @since   JDK1.0
  288.      */
  289.     public synchronized void mark(int readlimit) {
  290.     marklimit = readlimit;
  291.     markpos = pos;
  292.     }
  293.  
  294.     /**
  295.      * Repositions this stream to the position at the time the 
  296.      * <code>mark</code> method was last called on this input stream. 
  297.      * <p>
  298.      * If the stream has not been marked, or if the mark has been invalidated,
  299.      * an IOException is thrown. Stream marks are intended to be used in
  300.      * situations where you need to read ahead a little to see what's in
  301.      * the stream. Often this is most easily done by invoking some
  302.      * general parser. If the stream is of the type handled by the
  303.      * parser, it just chugs along happily. If the stream is not of
  304.      * that type, the parser should toss an exception when it fails. If an
  305.      * exception gets tossed within readlimit bytes, the parser will allow the
  306.      * outer code to reset the stream and to try another parser.
  307.      *
  308.      * @exception  IOException  if this stream has not been marked or
  309.      *               if the mark has been invalidated.
  310.      * @see        java.io.BufferedInputStream#mark(int)
  311.      * @since      JDK1.0
  312.      */
  313.     public synchronized void reset() throws IOException {
  314.     if (markpos < 0)
  315.         throw new IOException("Resetting to invalid mark");
  316.     pos = markpos;
  317.     }
  318.  
  319.     /**
  320.      * Tests if this input stream supports the <code>mark</code> 
  321.      * and <code>reset</code> methods. The <code>markSupported</code> 
  322.      * method of <code>BufferedInputStream</code> returns 
  323.      * <code>true</code>. 
  324.      *
  325.      * @return  a <code>boolean</code> indicating if this stream type supports
  326.      *          the <code>mark</code> and <code>reset</code> methods.
  327.      * @see     java.io.InputStream#mark(int)
  328.      * @see     java.io.InputStream#reset()
  329.      * @since   JDK1.0
  330.  
  331.      */
  332.     public boolean markSupported() {
  333.     return true;
  334.     }
  335. }
  336.