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方法来关闭流。这会释放与这个流关联的所有资源。