BufferedInputStream.java
上传用户:demmber
上传日期:2007-12-22
资源大小:717k
文件大小:6k
源码类别:

Java编程

开发平台:

Java

  1. /*
  2.  * @(#)BufferedInputStream.java 0.3-3 06/05/2001
  3.  *
  4.  *  This file is part of the HTTPClient package
  5.  *  Copyright (C) 1996-2001 Ronald Tschal鋜
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Lesser General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Lesser General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU Lesser General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20.  *  MA 02111-1307, USA
  21.  *
  22.  *  For questions, suggestions, bug-reports, enhancement-requests etc.
  23.  *  I may be contacted at:
  24.  *
  25.  *  ronald@innovation.ch
  26.  *
  27.  *  The HTTPClient's home page is located at:
  28.  *
  29.  *  http://www.innovation.ch/java/HTTPClient/ 
  30.  *
  31.  */
  32. package HTTPClient;
  33. import java.io.InputStream;
  34. import java.io.FilterInputStream;
  35. import java.io.IOException;
  36. /**
  37.  * This class is similar to java.io.BufferedInputStream, except that it fixes
  38.  * certain bugs and provides support for finding multipart boundaries.
  39.  *
  40.  * <P>Note: none of the methods here are synchronized because we assume the
  41.  * caller is already taking care of that.
  42.  *
  43.  * @version 0.3-3  06/05/2001
  44.  * @author Ronald Tschal鋜
  45.  */
  46. class BufferedInputStream extends FilterInputStream
  47. {
  48.     /** our read buffer */
  49.     private byte[] buffer = new byte[2000];
  50.     /** the next byte in the buffer at which to read */
  51.     private int    pos = 0;
  52.     /** the end of the valid data in the buffer */
  53.     private int    end = 0;
  54.     /** the current mark position, or -1 if none */
  55.     private int    mark_pos = -1;
  56.     /**
  57.      * the large read threashhold: reads larger than this aren't buffered if
  58.      * both the current buffer is empty and no mark has been set. This is just
  59.      * an attempt to balance copying vs. multiple reads.
  60.      */
  61.     private int    lr_thrshld = 1500;
  62.     /**
  63.      * Create a new BufferedInputStream around the given input stream.
  64.      *
  65.      * @param stream  the underlying input stream to use
  66.      */
  67.     BufferedInputStream(InputStream stream)
  68.     {
  69. super(stream);
  70.     }
  71.     /**
  72.      * Read a single byte.
  73.      *
  74.      * @return the read byte, or -1 if the end of the stream has been reached
  75.      * @exception IOException if thrown by the underlying stream
  76.      */
  77.     public int read() throws IOException
  78.     {
  79. if (pos >= end)
  80.     fillBuff();
  81. return (end > pos) ? (buffer[pos++] & 0xFF) : -1;
  82.     }
  83.     /**
  84.      * Read a buffer full.
  85.      *
  86.      * @param buf  the buffer to read into
  87.      * @param off  the offset within <var>buf</var> at which to start writing
  88.      * @param len  the number of bytes to read
  89.      * @return the number of bytes read
  90.      * @exception IOException if thrown by the underlying stream
  91.      */
  92.     public int read(byte[] buf, int off, int len) throws IOException
  93.     {
  94. if (len <= 0)
  95.     return 0;
  96. // optimize for large reads
  97. if (pos >= end  &&  len >= lr_thrshld  &&  mark_pos < 0)
  98.     return in.read(buf, off, len);
  99. if (pos >= end)
  100.     fillBuff();
  101. if (pos >= end)
  102.     return -1;
  103. int left = end - pos;
  104. if (len > left)
  105.     len = left;
  106. System.arraycopy(buffer, pos, buf, off, len);
  107. pos += len;
  108. return len;
  109.     }
  110.     /**
  111.      * Skip the given number of bytes in the stream.
  112.      *
  113.      * @param n   the number of bytes to skip
  114.      * @return the actual number of bytes skipped
  115.      * @exception IOException if thrown by the underlying stream
  116.      */
  117.     public long skip(long n) throws IOException
  118.     {
  119. if (n <= 0)
  120.     return 0;
  121. int left = end - pos;
  122. if (n <= left)
  123. {
  124.     pos += n;
  125.     return n;
  126. }
  127. else
  128. {
  129.     pos = end;
  130.     return left + in.skip(n - left);
  131. }
  132.     }
  133.     /**
  134.      * Fill buffer by reading from the underlying stream. This assumes the
  135.      * current buffer is empty, i.e. pos == end.
  136.      */
  137.     private final void fillBuff() throws IOException
  138.     {
  139. if (mark_pos > 0) // keep the marked stuff around if possible
  140. {
  141.     // only copy if we don't have any space left
  142.     if (end >= buffer.length)
  143.     {
  144. System.arraycopy(buffer, mark_pos, buffer, 0, end - mark_pos);
  145. pos = end - mark_pos;
  146.     }
  147. }
  148. else if (mark_pos == 0  &&  end < buffer.length)
  149.     ; // pos == end, so we just fill what's left
  150. else
  151.     pos = 0; // try to fill complete buffer
  152. // make sure our state is consistent even if read() throws InterruptedIOException
  153. end = pos;
  154. int got = in.read(buffer, pos, buffer.length - pos);
  155. if (got > 0)
  156.     end = pos + got;
  157.     }
  158.     /**
  159.      * @return the number of bytes available for reading without blocking
  160.      * @exception IOException if the buffer is empty and the underlying stream has been
  161.      *                        closed
  162.      */
  163.     public int available() throws IOException
  164.     {
  165. int avail = end - pos;  
  166. if (avail == 0)
  167.     return in.available();
  168. try
  169.     { avail += in.available(); }
  170. catch (IOException ignored)
  171.     { /* ignore this because we have something available */ }
  172. return avail;
  173.     }
  174.     /**
  175.      * Mark the current read position so that we can start searching for the end boundary.
  176.      */
  177.     void markForSearch()
  178.     {
  179. mark_pos = pos;
  180.     }
  181.     /**
  182.      * Figures out how many bytes past the end of the multipart we read. If we
  183.      * found the end, it then resets the read pos to just past the end of the
  184.      * boundary and unsets the mark; if not found, is sets the mark_pos back
  185.      * enough from the current position so we can always be sure to find the
  186.      * boundary.
  187.      *
  188.      * @param search     the search string (end boundary)
  189.      * @param search_cmp the compiled info of the search string
  190.      * @return how many bytes past the end of the boundary we went; -1 if we
  191.      *         haven't gone passed it yet.
  192.      */
  193.     int pastEnd(byte[] search, int[] search_cmp)
  194.     {
  195. int idx = Util.findStr(search, search_cmp, buffer, mark_pos, pos);
  196. if (idx == -1)
  197.     mark_pos = (pos > search.length) ? pos - search.length : 0;
  198. else
  199. {
  200.     int eos  = idx + search.length;
  201.     idx      = pos - eos;
  202.     pos      = eos;
  203.     mark_pos = -1;
  204. }
  205. return idx;
  206.     }
  207. }