001 /* BufferedInputStream.java -- An input stream that implements buffering 002 Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package java.io; 040 041 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 042 * "The Java Language Specification", ISBN 0-201-63451-1 043 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. 044 * Status: Believed complete and correct. 045 */ 046 047 /** 048 * This subclass of <code>FilterInputStream</code> buffers input from an 049 * underlying implementation to provide a possibly more efficient read 050 * mechanism. It maintains the buffer and buffer state in instance 051 * variables that are available to subclasses. The default buffer size 052 * of 2048 bytes can be overridden by the creator of the stream. 053 * <p> 054 * This class also implements mark/reset functionality. It is capable 055 * of remembering any number of input bytes, to the limits of 056 * system memory or the size of <code>Integer.MAX_VALUE</code> 057 * <p> 058 * Please note that this class does not properly handle character 059 * encodings. Consider using the <code>BufferedReader</code> class which 060 * does. 061 * 062 * @author Aaron M. Renn (arenn@urbanophile.com) 063 * @author Warren Levy (warrenl@cygnus.com) 064 * @author Jeroen Frijters (jeroen@frijters.net) 065 */ 066 public class BufferedInputStream extends FilterInputStream 067 { 068 069 /** 070 * This is the default buffer size 071 */ 072 private static final int DEFAULT_BUFFER_SIZE = 2048; 073 074 /** 075 * The buffer used for storing data from the underlying stream. 076 */ 077 protected byte[] buf; 078 079 /** 080 * The number of valid bytes currently in the buffer. It is also the index 081 * of the buffer position one byte past the end of the valid data. 082 */ 083 protected int count; 084 085 /** 086 * The index of the next character that will by read from the buffer. 087 * When <code>pos == count</code>, the buffer is empty. 088 */ 089 protected int pos; 090 091 /** 092 * The value of <code>pos</code> when the <code>mark()</code> method was 093 * called. 094 * This is set to -1 if there is no mark set. 095 */ 096 protected int markpos = -1; 097 098 /** 099 * This is the maximum number of bytes than can be read after a 100 * call to <code>mark()</code> before the mark can be discarded. 101 * After this may bytes are read, the <code>reset()</code> method 102 * may not be called successfully. 103 */ 104 protected int marklimit; 105 106 /** 107 * This is the initial buffer size. When the buffer is grown because 108 * of marking requirements, it will be grown by bufferSize increments. 109 * The underlying stream will be read in chunks of bufferSize. 110 */ 111 private final int bufferSize; 112 113 /** 114 * This method initializes a new <code>BufferedInputStream</code> that will 115 * read from the specified subordinate stream with a default buffer size 116 * of 2048 bytes 117 * 118 * @param in The subordinate stream to read from 119 */ 120 public BufferedInputStream(InputStream in) 121 { 122 this(in, DEFAULT_BUFFER_SIZE); 123 } 124 125 /** 126 * This method initializes a new <code>BufferedInputStream</code> that will 127 * read from the specified subordinate stream with a buffer size that 128 * is specified by the caller. 129 * 130 * @param in The subordinate stream to read from 131 * @param size The buffer size to use 132 * 133 * @exception IllegalArgumentException when size is smaller then 1 134 */ 135 public BufferedInputStream(InputStream in, int size) 136 { 137 super(in); 138 if (size <= 0) 139 throw new IllegalArgumentException(); 140 buf = new byte[size]; 141 // initialize pos & count to bufferSize, to prevent refill from 142 // allocating a new buffer (if the caller starts out by calling mark()). 143 pos = count = bufferSize = size; 144 } 145 146 /** 147 * This method returns the number of bytes that can be read from this 148 * stream before a read can block. A return of 0 indicates that blocking 149 * might (or might not) occur on the very next read attempt. 150 * <p> 151 * The number of available bytes will be the number of read ahead bytes 152 * stored in the internal buffer plus the number of available bytes in 153 * the underlying stream. 154 * 155 * @return The number of bytes that can be read before blocking could occur 156 * 157 * @exception IOException If an error occurs 158 */ 159 public synchronized int available() throws IOException 160 { 161 return count - pos + in.available(); 162 } 163 164 /** 165 * This method closes the underlying input stream and frees any 166 * resources associated with it. Sets <code>buf</code> to <code>null</code>. 167 * 168 * @exception IOException If an error occurs. 169 */ 170 public void close() throws IOException 171 { 172 // Free up the array memory. 173 buf = null; 174 pos = count = 0; 175 markpos = -1; 176 in.close(); 177 } 178 179 /** 180 * This method marks a position in the input to which the stream can be 181 * "reset" by calling the <code>reset()</code> method. The parameter 182 * <code>readlimit</code> is the number of bytes that can be read from the 183 * stream after setting the mark before the mark becomes invalid. For 184 * example, if <code>mark()</code> is called with a read limit of 10, then 185 * when 11 bytes of data are read from the stream before the 186 * <code>reset()</code> method is called, then the mark is invalid and the 187 * stream object instance is not required to remember the mark. 188 * <p> 189 * Note that the number of bytes that can be remembered by this method 190 * can be greater than the size of the internal read buffer. It is also 191 * not dependent on the subordinate stream supporting mark/reset 192 * functionality. 193 * 194 * @param readlimit The number of bytes that can be read before the mark 195 * becomes invalid 196 */ 197 public synchronized void mark(int readlimit) 198 { 199 marklimit = readlimit; 200 markpos = pos; 201 } 202 203 /** 204 * This method returns <code>true</code> to indicate that this class 205 * supports mark/reset functionality. 206 * 207 * @return <code>true</code> to indicate that mark/reset functionality is 208 * supported 209 * 210 */ 211 public boolean markSupported() 212 { 213 return true; 214 } 215 216 /** 217 * This method reads an unsigned byte from the input stream and returns it 218 * as an int in the range of 0-255. This method also will return -1 if 219 * the end of the stream has been reached. 220 * <p> 221 * This method will block until the byte can be read. 222 * 223 * @return The byte read or -1 if end of stream 224 * 225 * @exception IOException If an error occurs 226 */ 227 public synchronized int read() throws IOException 228 { 229 if (pos >= count && !refill()) 230 return -1; // EOF 231 232 return buf[pos++] & 0xFF; 233 } 234 235 /** 236 * This method reads bytes from a stream and stores them into a caller 237 * supplied buffer. It starts storing the data at index <code>off</code> 238 * into the buffer and attempts to read <code>len</code> bytes. This method 239 * can return before reading the number of bytes requested, but it will try 240 * to read the requested number of bytes by repeatedly calling the underlying 241 * stream as long as available() for this stream continues to return a 242 * non-zero value (or until the requested number of bytes have been read). 243 * The actual number of bytes read is returned as an int. A -1 is returned 244 * to indicate the end of the stream. 245 * <p> 246 * This method will block until some data can be read. 247 * 248 * @param b The array into which the bytes read should be stored 249 * @param off The offset into the array to start storing bytes 250 * @param len The requested number of bytes to read 251 * 252 * @return The actual number of bytes read, or -1 if end of stream. 253 * 254 * @exception IOException If an error occurs. 255 * @exception IndexOutOfBoundsException when <code>off</code> or 256 * <code>len</code> are negative, or when <code>off + len</code> 257 * is larger then the size of <code>b</code>, 258 */ 259 public synchronized int read(byte[] b, int off, int len) throws IOException 260 { 261 if (off < 0 || len < 0 || b.length - off < len) 262 throw new IndexOutOfBoundsException(); 263 264 if (len == 0) 265 return 0; 266 267 if (pos >= count && !refill()) 268 return -1; // No bytes were read before EOF. 269 270 int totalBytesRead = Math.min(count - pos, len); 271 System.arraycopy(buf, pos, b, off, totalBytesRead); 272 pos += totalBytesRead; 273 off += totalBytesRead; 274 len -= totalBytesRead; 275 276 while (len > 0 && in.available() > 0 && refill()) 277 { 278 int remain = Math.min(count - pos, len); 279 System.arraycopy(buf, pos, b, off, remain); 280 pos += remain; 281 off += remain; 282 len -= remain; 283 totalBytesRead += remain; 284 } 285 286 return totalBytesRead; 287 } 288 289 /** 290 * This method resets a stream to the point where the <code>mark()</code> 291 * method was called. Any bytes that were read after the mark point was 292 * set will be re-read during subsequent reads. 293 * <p> 294 * This method will throw an IOException if the number of bytes read from 295 * the stream since the call to <code>mark()</code> exceeds the mark limit 296 * passed when establishing the mark. 297 * 298 * @exception IOException If <code>mark()</code> was never called or more 299 * then <code>marklimit</code> bytes were read since the last 300 * call to <code>mark()</code> 301 */ 302 public synchronized void reset() throws IOException 303 { 304 if (markpos == -1) 305 throw new IOException(buf == null ? "Stream closed." : "Invalid mark."); 306 307 pos = markpos; 308 } 309 310 /** 311 * This method skips the specified number of bytes in the stream. It 312 * returns the actual number of bytes skipped, which may be less than the 313 * requested amount. 314 * 315 * @param n The requested number of bytes to skip 316 * 317 * @return The actual number of bytes skipped. 318 * 319 * @exception IOException If an error occurs 320 */ 321 public synchronized long skip(long n) throws IOException 322 { 323 if (buf == null) 324 throw new IOException("Stream closed."); 325 326 final long origN = n; 327 328 while (n > 0L) 329 { 330 if (pos >= count) 331 { 332 if (markpos == -1) 333 { 334 // Buffer is empty and no mark is set, skip on the 335 // underlying stream. 336 n -= in.skip(n); 337 break; 338 } 339 else if (!refill()) 340 break; 341 } 342 343 int numread = (int) Math.min((long) (count - pos), n); 344 pos += numread; 345 n -= numread; 346 } 347 348 return origN - n; 349 } 350 351 // GCJ LOCAL: package-private for use by InputStreamReader 352 /** 353 * Called to refill the buffer (when count is equal to pos). 354 * 355 * @return <code>true</code> when at least one additional byte was read 356 * into <code>buf</code>, <code>false</code> otherwise (at EOF). 357 */ 358 boolean refill() throws IOException 359 { 360 if (buf == null) 361 throw new IOException("Stream closed."); 362 363 if (markpos == -1 || count - markpos >= marklimit) 364 { 365 markpos = -1; 366 pos = count = 0; 367 } 368 else 369 { 370 byte[] newbuf = buf; 371 if (markpos < bufferSize) 372 { 373 newbuf = new byte[count - markpos + bufferSize]; 374 } 375 System.arraycopy(buf, markpos, newbuf, 0, count - markpos); 376 buf = newbuf; 377 count -= markpos; 378 pos -= markpos; 379 markpos = 0; 380 } 381 382 int numread = in.read(buf, count, bufferSize); 383 384 if (numread <= 0) // EOF 385 return false; 386 387 count += numread; 388 return true; 389 } 390 }