GNU Classpath (0.95) | |
Frames | No Frames |
1: /* BufferedInputStream.java -- An input stream that implements buffering 2: Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.io; 40: 41: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 42: * "The Java Language Specification", ISBN 0-201-63451-1 43: * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. 44: * Status: Believed complete and correct. 45: */ 46: 47: /** 48: * This subclass of <code>FilterInputStream</code> buffers input from an 49: * underlying implementation to provide a possibly more efficient read 50: * mechanism. It maintains the buffer and buffer state in instance 51: * variables that are available to subclasses. The default buffer size 52: * of 2048 bytes can be overridden by the creator of the stream. 53: * <p> 54: * This class also implements mark/reset functionality. It is capable 55: * of remembering any number of input bytes, to the limits of 56: * system memory or the size of <code>Integer.MAX_VALUE</code> 57: * <p> 58: * Please note that this class does not properly handle character 59: * encodings. Consider using the <code>BufferedReader</code> class which 60: * does. 61: * 62: * @author Aaron M. Renn (arenn@urbanophile.com) 63: * @author Warren Levy (warrenl@cygnus.com) 64: * @author Jeroen Frijters (jeroen@frijters.net) 65: */ 66: public class BufferedInputStream extends FilterInputStream 67: { 68: 69: /** 70: * This is the default buffer size 71: */ 72: private static final int DEFAULT_BUFFER_SIZE = 2048; 73: 74: /** 75: * The buffer used for storing data from the underlying stream. 76: */ 77: protected byte[] buf; 78: 79: /** 80: * The number of valid bytes currently in the buffer. It is also the index 81: * of the buffer position one byte past the end of the valid data. 82: */ 83: protected int count; 84: 85: /** 86: * The index of the next character that will by read from the buffer. 87: * When <code>pos == count</code>, the buffer is empty. 88: */ 89: protected int pos; 90: 91: /** 92: * The value of <code>pos</code> when the <code>mark()</code> method was 93: * called. 94: * This is set to -1 if there is no mark set. 95: */ 96: protected int markpos = -1; 97: 98: /** 99: * 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 + super.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: super.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 && super.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 && !refill()) 331: break; 332: 333: int numread = (int) Math.min((long) (count - pos), n); 334: pos += numread; 335: n -= numread; 336: } 337: 338: return origN - n; 339: } 340: 341: /** 342: * Called to refill the buffer (when count is equal to pos). 343: * 344: * @return <code>true</code> when at least one additional byte was read 345: * into <code>buf</code>, <code>false</code> otherwise (at EOF). 346: */ 347: private boolean refill() throws IOException 348: { 349: if (buf == null) 350: throw new IOException("Stream closed."); 351: 352: if (markpos == -1 || count - markpos >= marklimit) 353: { 354: markpos = -1; 355: pos = count = 0; 356: } 357: else 358: { 359: byte[] newbuf = buf; 360: if (markpos < bufferSize) 361: { 362: newbuf = new byte[count - markpos + bufferSize]; 363: } 364: System.arraycopy(buf, markpos, newbuf, 0, count - markpos); 365: buf = newbuf; 366: count -= markpos; 367: pos -= markpos; 368: markpos = 0; 369: } 370: 371: int numread = super.read(buf, count, bufferSize); 372: 373: if (numread <= 0) // EOF 374: return false; 375: 376: count += numread; 377: return true; 378: } 379: }
GNU Classpath (0.95) |