此类用于向文件中写入数据或是创建文件。
首先对于其构造方法,虽然有四个,分别是
1.public FileOutputStream(String name) throws FileNotFoundException { this(name != null ? new File(name) : null, false); } 2.public FileOutputStream(String name, boolean append) throws FileNotFoundException { this(name != null ? new File(name) : null, append); } 3.public FileOutputStream(File file) throws FileNotFoundException { this(file, false); } 4.public FileOutputStream(File file, boolean append) throws FileNotFoundException { String name = (file != null ? file.getPath() : null); SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkWrite(name); } if (name == null) { throw new NullPointerException(); } if (file.isInvalid()) { throw new FileNotFoundException("Invalid file path"); } this.fd = new FileDescriptor(); fd.attach(this); this.append = append; this.path = name; open(name, append); }
可以看到这4个构造方法,究其本质,其实都是第四个构造方法。上面的三个构造方法不过是调用这第四个构造方法而已,name代表路径,append为true时表示写入的字节添加至文件的末尾,为false时表示新内容直接覆盖原内容。
有趣的是FileOutputStream的构造方法在输入路径构造时若文件不存在并不会报错,而是直接创建该文件,只有不存在且无法创建文件时才会报FileNotFoundException异常,所以通常来说,该流的构造方法也可以用于生成系统文件。
接着是FileOutputStream的一些常用API。
1.public void write(int b) throws IOException { write(b, append); }//这里调用的这个write是一个native方法,看不到源码,功能是写一个字节到输出流中 2.public void write(byte b[]) throws IOException { writeBytes(b, 0, b.length, append); }//此方法调用的是writebytes方法,同样也是一个native方法,功能是写入b.length个字 //节到输出流中。这里append就是构造方法中的那个append,默认为false
这里的writeBytes方法可以参照其父类OutputStream中的write方法来理解
public void write(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } for (int i = 0 ; i < len ; i++) { write(b[off + i]); } }
可以看到也不过是使用循环多次调用write(int b)方法来实现的。同时该方法还能灵活控制想要输入的内容,off为偏移量,len代表要输出的长度。所以这几种write方法从效率上来说,也差不多。
无论输入流还是输出流,最后使用完了都必须要关闭,不然会一直占有系统资源,所以使用完毕请调用close方法将其释放
public void close() throws IOException { synchronized (closeLock) { if (closed) { return; } closed = true; } if (channel != null) { channel.close(); } fd.closeAll(new Closeable() { public void close() throws IOException { close0(); } }); }