Buffered Streams

Buffered input streams read more data than they initially need into a buffer (an internal array of bytes). When the stream’s read() methods are invoked, the data is removed from the buffer rather than the underlying stream. When the buffer runs out of data, the buffered stream refills its buffer from the underlying stream. Likewise, buffered output streams store data in an internal byte array until the buffer is full or the stream is flushed; then the data is written out to the underlying output stream in one swoop. In situations where it’s almost as fast to read or write several hundred bytes from the underlying stream as it is to read or write a single byte, a buffered stream can provide a significant performance gain.

There are two BufferedInputStream constructors and two BufferedOutputStream constructors:

public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in, int size)
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStream out, int size)

The first argument is the underlying stream from which data will be read or to which data will be written. The size argument is the number of bytes in the buffer. If a size isn’t specified, a 2048-byte buffer is used. The best size for the buffer depends on the platform and is generally related to the block size of the disk (at least for file streams). Less than 512 bytes is probably too small and more than 4096 bytes is probably too large. Ideally, you want an integral multiple of the block size of the disk. However, you might want to use smaller buffer sizes for unreliable network connections. For example:

URL u = new URL("http://java.developer.com");
BufferedInputStream bis = new BufferedInputStream(u.openStream(), 256);

Example 6.4 copies files named on the command line to System.out with buffered reads and writes.

Example 6-4. A BufferedStreamCopier

package com.macfaq.io;
import java.io.*;

public class BufferedStreamCopier {

  public static void main(String[] args) {

    try {
      copy(System.in, System.out);
    }
    catch (IOException e) {System.err.println(e);}
  }

  public static void copy(InputStream in, OutputStream out) 
   throws IOException {

    // Do not allow other threads to read from the input
    // or write to the output while copying is taking place.
    synchronized (in) {
      synchronized (out) {
        BufferedInputStream bin = new BufferedInputStream(in);
        BufferedOutputStream bout = new BufferedOutputStream(out);
		
        while (true) {
          int datum = bin.read();
          if (datum == -1) break;
          bout.write(datum);
        }
        bout.flush();
      }
    }
  }
}

This copy() method copies byte by byte, which is normally not very efficient. However, almost all the copies take place in memory, because the input stream and the output stream are buffered. Therefore, this is reasonably quick.

It wouldn’t hurt to read and write byte arrays in the copy() method instead of individual bytes, as long as the arrays you were reading and writing were significantly smaller than the buffer size. However, one level of buffering is usually sufficient. Detailed performance calculations depend on the virtual machine and the host OS, so it’s hard to make any definite conclusions.

Also note that the output stream is deliberately flushed. The data only reaches its eventual destination in the underlying stream out when the stream is flushed or the buffer fills up. Therefore, it’s important to call flush() explicitly before the method returns.

BufferedInputStream Details

The buffer and the current state of the buffer are stored in protected fields. The buffer itself is a byte array called buf; the number of bytes in the buffer is an int named count; the index of the next byte that will be returned by read() is an int called pos; the mark, if any, is an int called markpos; the read-ahead limit be- fore the mark is invalidated is an int called marklimit. Subclasses of BufferedInputStream can directly access all these fields, which can be important for performance.

protected byte[] buf
protected int count
protected int pos
protected int markpos
protected int marklimit

BufferedInputStream only overrides methods from InputStream. It does not declare any new methods of its own. Marking and resetting are supported.

public synchronized int read() throws IOException
public synchronized int read(byte[] data, int offset, int length) 
                    throws IOException
public synchronized long skip(long n) throws IOException
public synchronized int available() throws IOException
public synchronized void mark(int readLimit)
public synchronized void reset() throws IOException
public boolean markSupported()

In Java 2 and later, the two multibyte read() methods try to fill the specified array or subarray completely by reading repeatedly from the underlying input stream. They return only when the requested number of bytes have been read, the end of stream is reached, or the underlying stream would block. This is not the case for most input streams (including buffered input streams in Java 1.1.x and earlier), which only attempt one read from the underlying stream or data source before returning.

BufferedOutputStream Details

BufferedOutputStream also stores the buffer in a protected byte array named buf and the index of the next place in the array where a byte will be stored in an int field named pos. BufferedOutputStream does not expose the number of bytes in the buffer.

protected byte buf[]
protected int pos

BufferedOutputStream only overrides three methods from OutputStream. It does not declare any new methods.

public synchronized void write(int b) throws IOException
public synchronized void write(byte data[], int offset, int length) 
                    throws IOException
public synchronized void flush() throws IOException

These methods are invoked exactly as they would be for any output stream. The only difference is that writes place data in the buffer rather than directly on the underlying output stream.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.53.166