175 * and saves its argument, the input stream
176 * <code>in</code>, for later use. An internal
177 * buffer array is created and stored in <code>buf</code>.
178 *
179 * @param in the underlying input stream.
180 */
181 public BufferedInputStream(InputStream in) {
182 this(in, DEFAULT_BUFFER_SIZE);
183 }
184
185 /**
186 * Creates a <code>BufferedInputStream</code>
187 * with the specified buffer size,
188 * and saves its argument, the input stream
189 * <code>in</code>, for later use. An internal
190 * buffer array of length <code>size</code>
191 * is created and stored in <code>buf</code>.
192 *
193 * @param in the underlying input stream.
194 * @param size the buffer size.
195 * @exception IllegalArgumentException if {@code size <= 0}.
196 */
197 public BufferedInputStream(InputStream in, int size) {
198 super(in);
199 if (size <= 0) {
200 throw new IllegalArgumentException("Buffer size <= 0");
201 }
202 buf = new byte[size];
203 }
204
205 /**
206 * Fills the buffer with more data, taking into account
207 * shuffling and other tricks for dealing with marks.
208 * Assumes that it is being called by a synchronized method.
209 * This method also assumes that all data has already been read in,
210 * hence pos > count.
211 */
212 private void fill() throws IOException {
213 byte[] buffer = getBufIfOpen();
214 if (markpos < 0)
215 pos = 0; /* no mark: throw away the buffer */
237 // But for now, the only way CAS can fail is via close.
238 // assert buf == null;
239 throw new IOException("Stream closed");
240 }
241 buffer = nbuf;
242 }
243 }
244 count = pos;
245 int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
246 if (n > 0)
247 count = n + pos;
248 }
249
250 /**
251 * See
252 * the general contract of the <code>read</code>
253 * method of <code>InputStream</code>.
254 *
255 * @return the next byte of data, or <code>-1</code> if the end of the
256 * stream is reached.
257 * @exception IOException if this input stream has been closed by
258 * invoking its {@link #close()} method,
259 * or an I/O error occurs.
260 * @see java.io.FilterInputStream#in
261 */
262 public synchronized int read() throws IOException {
263 if (pos >= count) {
264 fill();
265 if (pos >= count)
266 return -1;
267 }
268 return getBufIfOpen()[pos++] & 0xff;
269 }
270
271 /**
272 * Read characters into a portion of an array, reading from the underlying
273 * stream at most once if necessary.
274 */
275 private int read1(byte[] b, int off, int len) throws IOException {
276 int avail = count - pos;
277 if (avail <= 0) {
308 *
309 * <li> The <code>read</code> method of the underlying stream returns
310 * <code>-1</code>, indicating end-of-file, or
311 *
312 * <li> The <code>available</code> method of the underlying stream
313 * returns zero, indicating that further input requests would block.
314 *
315 * </ul> If the first <code>read</code> on the underlying stream returns
316 * <code>-1</code> to indicate end-of-file then this method returns
317 * <code>-1</code>. Otherwise this method returns the number of bytes
318 * actually read.
319 *
320 * <p> Subclasses of this class are encouraged, but not required, to
321 * attempt to read as many bytes as possible in the same fashion.
322 *
323 * @param b destination buffer.
324 * @param off offset at which to start storing bytes.
325 * @param len maximum number of bytes to read.
326 * @return the number of bytes read, or <code>-1</code> if the end of
327 * the stream has been reached.
328 * @exception IOException if this input stream has been closed by
329 * invoking its {@link #close()} method,
330 * or an I/O error occurs.
331 */
332 public synchronized int read(byte b[], int off, int len)
333 throws IOException
334 {
335 getBufIfOpen(); // Check for closed stream
336 if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
337 throw new IndexOutOfBoundsException();
338 } else if (len == 0) {
339 return 0;
340 }
341
342 int n = 0;
343 for (;;) {
344 int nread = read1(b, off + n, len - n);
345 if (nread <= 0)
346 return (n == 0) ? nread : n;
347 n += nread;
348 if (n >= len)
383 }
384
385 long skipped = (avail < n) ? avail : n;
386 pos += skipped;
387 return skipped;
388 }
389
390 /**
391 * Returns an estimate of the number of bytes that can be read (or
392 * skipped over) from this input stream without blocking by the next
393 * invocation of a method for this input stream. The next invocation might be
394 * the same thread or another thread. A single read or skip of this
395 * many bytes will not block, but may read or skip fewer bytes.
396 * <p>
397 * This method returns the sum of the number of bytes remaining to be read in
398 * the buffer (<code>count - pos</code>) and the result of calling the
399 * {@link java.io.FilterInputStream#in in}.available().
400 *
401 * @return an estimate of the number of bytes that can be read (or skipped
402 * over) from this input stream without blocking.
403 * @exception IOException if this input stream has been closed by
404 * invoking its {@link #close()} method,
405 * or an I/O error occurs.
406 */
407 public synchronized int available() throws IOException {
408 int n = count - pos;
409 int avail = getInIfOpen().available();
410 return n > (Integer.MAX_VALUE - avail)
411 ? Integer.MAX_VALUE
412 : n + avail;
413 }
414
415 /**
416 * See the general contract of the <code>mark</code>
417 * method of <code>InputStream</code>.
418 *
419 * @param readlimit the maximum limit of bytes that can be read before
420 * the mark position becomes invalid.
421 * @see java.io.BufferedInputStream#reset()
422 */
423 public synchronized void mark(int readlimit) {
424 marklimit = readlimit;
425 markpos = pos;
426 }
427
428 /**
429 * See the general contract of the <code>reset</code>
430 * method of <code>InputStream</code>.
431 * <p>
432 * If <code>markpos</code> is <code>-1</code>
433 * (no mark has been set or the mark has been
434 * invalidated), an <code>IOException</code>
435 * is thrown. Otherwise, <code>pos</code> is
436 * set equal to <code>markpos</code>.
437 *
438 * @exception IOException if this stream has not been marked or,
439 * if the mark has been invalidated, or the stream
440 * has been closed by invoking its {@link #close()}
441 * method, or an I/O error occurs.
442 * @see java.io.BufferedInputStream#mark(int)
443 */
444 public synchronized void reset() throws IOException {
445 getBufIfOpen(); // Cause exception if closed
446 if (markpos < 0)
447 throw new IOException("Resetting to invalid mark");
448 pos = markpos;
449 }
450
451 /**
452 * Tests if this input stream supports the <code>mark</code>
453 * and <code>reset</code> methods. The <code>markSupported</code>
454 * method of <code>BufferedInputStream</code> returns
455 * <code>true</code>.
456 *
457 * @return a <code>boolean</code> indicating if this stream type supports
458 * the <code>mark</code> and <code>reset</code> methods.
459 * @see java.io.InputStream#mark(int)
460 * @see java.io.InputStream#reset()
461 */
462 public boolean markSupported() {
463 return true;
464 }
465
466 /**
467 * Closes this input stream and releases any system resources
468 * associated with the stream.
469 * Once the stream has been closed, further read(), available(), reset(),
470 * or skip() invocations will throw an IOException.
471 * Closing a previously closed stream has no effect.
472 *
473 * @exception IOException if an I/O error occurs.
474 */
475 public void close() throws IOException {
476 byte[] buffer;
477 while ( (buffer = buf) != null) {
478 if (U.compareAndSetReference(this, BUF_OFFSET, buffer, null)) {
479 InputStream input = in;
480 in = null;
481 if (input != null)
482 input.close();
483 return;
484 }
485 // Else retry in case a new buf was CASed in fill()
486 }
487 }
488 }
|
175 * and saves its argument, the input stream
176 * <code>in</code>, for later use. An internal
177 * buffer array is created and stored in <code>buf</code>.
178 *
179 * @param in the underlying input stream.
180 */
181 public BufferedInputStream(InputStream in) {
182 this(in, DEFAULT_BUFFER_SIZE);
183 }
184
185 /**
186 * Creates a <code>BufferedInputStream</code>
187 * with the specified buffer size,
188 * and saves its argument, the input stream
189 * <code>in</code>, for later use. An internal
190 * buffer array of length <code>size</code>
191 * is created and stored in <code>buf</code>.
192 *
193 * @param in the underlying input stream.
194 * @param size the buffer size.
195 * @throws IllegalArgumentException if {@code size <= 0}.
196 */
197 public BufferedInputStream(InputStream in, int size) {
198 super(in);
199 if (size <= 0) {
200 throw new IllegalArgumentException("Buffer size <= 0");
201 }
202 buf = new byte[size];
203 }
204
205 /**
206 * Fills the buffer with more data, taking into account
207 * shuffling and other tricks for dealing with marks.
208 * Assumes that it is being called by a synchronized method.
209 * This method also assumes that all data has already been read in,
210 * hence pos > count.
211 */
212 private void fill() throws IOException {
213 byte[] buffer = getBufIfOpen();
214 if (markpos < 0)
215 pos = 0; /* no mark: throw away the buffer */
237 // But for now, the only way CAS can fail is via close.
238 // assert buf == null;
239 throw new IOException("Stream closed");
240 }
241 buffer = nbuf;
242 }
243 }
244 count = pos;
245 int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
246 if (n > 0)
247 count = n + pos;
248 }
249
250 /**
251 * See
252 * the general contract of the <code>read</code>
253 * method of <code>InputStream</code>.
254 *
255 * @return the next byte of data, or <code>-1</code> if the end of the
256 * stream is reached.
257 * @throws IOException if this input stream has been closed by
258 * invoking its {@link #close()} method,
259 * or an I/O error occurs.
260 * @see java.io.FilterInputStream#in
261 */
262 public synchronized int read() throws IOException {
263 if (pos >= count) {
264 fill();
265 if (pos >= count)
266 return -1;
267 }
268 return getBufIfOpen()[pos++] & 0xff;
269 }
270
271 /**
272 * Read characters into a portion of an array, reading from the underlying
273 * stream at most once if necessary.
274 */
275 private int read1(byte[] b, int off, int len) throws IOException {
276 int avail = count - pos;
277 if (avail <= 0) {
308 *
309 * <li> The <code>read</code> method of the underlying stream returns
310 * <code>-1</code>, indicating end-of-file, or
311 *
312 * <li> The <code>available</code> method of the underlying stream
313 * returns zero, indicating that further input requests would block.
314 *
315 * </ul> If the first <code>read</code> on the underlying stream returns
316 * <code>-1</code> to indicate end-of-file then this method returns
317 * <code>-1</code>. Otherwise this method returns the number of bytes
318 * actually read.
319 *
320 * <p> Subclasses of this class are encouraged, but not required, to
321 * attempt to read as many bytes as possible in the same fashion.
322 *
323 * @param b destination buffer.
324 * @param off offset at which to start storing bytes.
325 * @param len maximum number of bytes to read.
326 * @return the number of bytes read, or <code>-1</code> if the end of
327 * the stream has been reached.
328 * @throws IOException if this input stream has been closed by
329 * invoking its {@link #close()} method,
330 * or an I/O error occurs.
331 */
332 public synchronized int read(byte b[], int off, int len)
333 throws IOException
334 {
335 getBufIfOpen(); // Check for closed stream
336 if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
337 throw new IndexOutOfBoundsException();
338 } else if (len == 0) {
339 return 0;
340 }
341
342 int n = 0;
343 for (;;) {
344 int nread = read1(b, off + n, len - n);
345 if (nread <= 0)
346 return (n == 0) ? nread : n;
347 n += nread;
348 if (n >= len)
383 }
384
385 long skipped = (avail < n) ? avail : n;
386 pos += skipped;
387 return skipped;
388 }
389
390 /**
391 * Returns an estimate of the number of bytes that can be read (or
392 * skipped over) from this input stream without blocking by the next
393 * invocation of a method for this input stream. The next invocation might be
394 * the same thread or another thread. A single read or skip of this
395 * many bytes will not block, but may read or skip fewer bytes.
396 * <p>
397 * This method returns the sum of the number of bytes remaining to be read in
398 * the buffer (<code>count - pos</code>) and the result of calling the
399 * {@link java.io.FilterInputStream#in in}.available().
400 *
401 * @return an estimate of the number of bytes that can be read (or skipped
402 * over) from this input stream without blocking.
403 * @throws IOException if this input stream has been closed by
404 * invoking its {@link #close()} method,
405 * or an I/O error occurs.
406 */
407 public synchronized int available() throws IOException {
408 int n = count - pos;
409 int avail = getInIfOpen().available();
410 return n > (Integer.MAX_VALUE - avail)
411 ? Integer.MAX_VALUE
412 : n + avail;
413 }
414
415 /**
416 * See the general contract of the <code>mark</code>
417 * method of <code>InputStream</code>.
418 *
419 * @param readlimit the maximum limit of bytes that can be read before
420 * the mark position becomes invalid.
421 * @see java.io.BufferedInputStream#reset()
422 */
423 public synchronized void mark(int readlimit) {
424 marklimit = readlimit;
425 markpos = pos;
426 }
427
428 /**
429 * See the general contract of the <code>reset</code>
430 * method of <code>InputStream</code>.
431 * <p>
432 * If <code>markpos</code> is <code>-1</code>
433 * (no mark has been set or the mark has been
434 * invalidated), an <code>IOException</code>
435 * is thrown. Otherwise, <code>pos</code> is
436 * set equal to <code>markpos</code>.
437 *
438 * @throws IOException if this stream has not been marked or,
439 * if the mark has been invalidated, or the stream
440 * has been closed by invoking its {@link #close()}
441 * method, or an I/O error occurs.
442 * @see java.io.BufferedInputStream#mark(int)
443 */
444 public synchronized void reset() throws IOException {
445 getBufIfOpen(); // Cause exception if closed
446 if (markpos < 0)
447 throw new IOException("Resetting to invalid mark");
448 pos = markpos;
449 }
450
451 /**
452 * Tests if this input stream supports the <code>mark</code>
453 * and <code>reset</code> methods. The <code>markSupported</code>
454 * method of <code>BufferedInputStream</code> returns
455 * <code>true</code>.
456 *
457 * @return a <code>boolean</code> indicating if this stream type supports
458 * the <code>mark</code> and <code>reset</code> methods.
459 * @see java.io.InputStream#mark(int)
460 * @see java.io.InputStream#reset()
461 */
462 public boolean markSupported() {
463 return true;
464 }
465
466 /**
467 * Closes this input stream and releases any system resources
468 * associated with the stream.
469 * Once the stream has been closed, further read(), available(), reset(),
470 * or skip() invocations will throw an IOException.
471 * Closing a previously closed stream has no effect.
472 *
473 * @throws IOException if an I/O error occurs.
474 */
475 public void close() throws IOException {
476 byte[] buffer;
477 while ( (buffer = buf) != null) {
478 if (U.compareAndSetReference(this, BUF_OFFSET, buffer, null)) {
479 InputStream input = in;
480 in = null;
481 if (input != null)
482 input.close();
483 return;
484 }
485 // Else retry in case a new buf was CASed in fill()
486 }
487 }
488 }
|