java的基本输出流是java.io.OutputStream

public abstract class OutputStream implements Closeable, Flushable

 

此类提供了写入数据的基本方法,这些方法包括:


public abstract void write(int b) throws IOException



public void write(byte b[]) throws IOException
public void write(byte b[], int off, int len) throws IOException
public void flush() throws IOException
public void close() throws IOException

OutputStream的基本方法是write(int b)。这个方法接受一个0-255之间的整数作为参数,将对应的字节写入到输出流中。这个方法写为抽象方法,因为各个子类需要对它进行修改来处理特定的媒介。

    ByteArrayOutputStream使用纯java的方法实现此方法,将字节复制到数组中,

public synchronized void write(int b) {
	int newcount = count + 1;
	if (newcount > buf.length) {
            buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
	}
	buf[count] = (byte)b;
	count = newcount;
    }

而FileOutputStream使用native方法来实现此方法。

public native void write(int b) throws IOException;

虽然这个方法接受一个int作为参数,但它实际上是写入一个无符号字节。java没有无符号字节数据类型,所以要使用int来代替。无符号字节和有符号字节之间的唯一区别在于解释。他们都是由8个位组成,当使用write(int  b)将int写入网络连接时,只有8个数据位放在线缆上。如果0~255之外的int传递给write方法,那么将写入此数字的最低字节,其他三个字节将被忽略。

    OutputStream类对write(int b)方法的doc解释也说明了这点。


/**
     * Writes the specified byte to this output stream. The general 
     * contract for <code>write</code> is that one byte is written 
     * to the output stream. The byte to be written is the eight 
     * low-order bits of the argument <code>b</code>. The 24 
     * high-order bits of <code>b</code> are ignored.
     * <p>
     * Subclasses of <code>OutputStream</code> must provide an 
     * implementation for this method. 
     *
     * @param      b   the <code>byte</code>.
     * @exception  IOException  if an I/O error occurs. In particular, 
     *             an <code>IOException</code> may be thrown if the 
     *             output stream has been closed.
     */

    一次写入一个字节常常效率不高。例如,流出以太网卡的每个TCP分片至少包含用于路由和纠错等开销的40个字节。如果每个字节都单独发送,那么相对于你所认为的数据,可能会有41倍之多的数据在填充网络!因此,大多数TCP/IP的实现都会在某种程度上缓存数据。他们在内存中积累数据,只有积累到一定量的数据后,或者经过一段时间后,才将所积累的数据发送到最终目的地。使用write(byte[] date) 或者write(byte[] date, int offset, int length)通常比一次发送data数组中的一个字节要快的多。

    与网络硬件中缓存一样,流还可以再软件中得到缓存,即直接在java代码中缓存。一般来说可以通过把BuferedOutputStream或BufferedWriter链接到底层流上来实现。因此在写入数据完成后,刷新(flush)输出流是很重要的。

一个流的操作时,要调用器close方法来关闭流。这会释放与这个流关联的所有资源。