【给JDK IO源码加点注释】02 FileInputStream、FileOutputStream
package java.io; import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; /** *FileInputStream是一个从文件获取字节流的类 * @since 1.0 */ public class FileInputStream extends InputStream { /* 文件描述符用于表示一个打开的文件*/ private final FileDescriptor fd; /**文件的路径 */ private final String path; private volatile FileChannel channel; //用于同步操作的锁 private final Object closeLock = new Object(); //流是否关闭标志 private volatile boolean closed; /** * 使用文件的绝对路径或者相对路径名创建文件输入流 * @param 文件路径 * @exception FileNotFoundException 如果文件不存在t ,传入的是一个目录名以及因为其他原因不能打开文件。 * @exception SecurityException 没有读取权限 */ public FileInputStream(String name) throws FileNotFoundException { //调用下面一个构造方法 this(name != null ? new File(name) : null); } /** *通过file对象创建输入流 * * @param file 需要读取的file对象。 * @exception FileNotFoundException 如果文件不存在t ,传入的是一个目录名以及因为其他原因不能打开文件。 * @exception SecurityException 没有读取权限 * @see java.io.File#getPath() * @see java.lang.SecurityManager#checkRead(java.lang.String) */ public FileInputStream(File file) throws FileNotFoundException { String name = (file != null ? file.getPath() : null); SecurityManager security = System.getSecurityManager(); if (security != null) { //检查是否有读取权限,没有则抛出SecurityException security.checkRead(name); } if (name == null) { throw new NullPointerException(); } //判断文件路径是否有效(其实是判断路径中是否有空格,不代表文件存在) if (file.isInvalid()) { throw new FileNotFoundException("Invalid file path"); } //初始化一个FileDescriptor用于描述文件连接 fd = new FileDescriptor(); //将this注册到fd对象中。 fd.attach(this); path = name; open(name); } /** * 通过FileDescriptor(代表一个已经存在的文件连接)来创建流 *通过同一个fd创建的流在其中一个关闭时全部都会关闭。 * @param fdObj filedescriptor对象(可通过getFD()获取) * @throws SecurityException 文件不可读 * @see SecurityManager#checkRead(java.io.FileDescriptor) */ public FileInputStream(FileDescriptor fdObj) { SecurityManager security = System.getSecurityManager(); if (fdObj == null) { throw new NullPointerException(); } if (security != null) { security.checkRead(fdObj); } fd = fdObj; path = null; //将this注册到fd对象中。 fd.attach(this); } /** *读取一个字节 */ public int read() throws IOException { return read0(); } /** *参考InputStream */ public int read(byte b[]) throws IOException { return readBytes(b, 0, b.length); } /** *参考InputStream */ public int read(byte b[], int off, int len) throws IOException { return readBytes(b, off, len); } /** * 跳过制定字节数 * @param n 需要跳过的字节数是 * @return 实际跳过的字节数。 * @exception IOException */ public long skip(long n) throws IOException { return skip0(n); } /** * * @return 返回一个估计的可读字节数 * @exception IOException */ public int available() throws IOException { return available0(); } /** *关闭当前流并释放与当前流关联的系统资源 * * @exception IOException if an I/O error occurs. * * @revised 1.4 * @spec JSR-51 */ public void close() throws IOException { //判断流是否已经关闭,已关闭直接返回。 if (closed) { return; } //获取锁 synchronized (closeLock) { //双重检测机制,防止多次关闭流。 if (closed) { return; } closed = true; } FileChannel fc = channel; if (fc != null) { // possible race with getChannel(), benign since // FileChannel.close is final and idempotent fc.close(); } //调用fd的closeAll方法,此方法会关闭所有注册到此fd对象中的流。 /**例如 *FileInputStream in = new FileInputStream("src\\test.txt"); *FileInputStream in2 = new FileInputStream(in.getFD()); *in.close(); *in2.read(); *这段代码会抛出IOException:Stream Closed */ fd.closeAll(new Closeable() { public void close() throws IOException { close0(); } }); } /** * 返回fd对象即当前的文件连接 * @return 与当前流关联的fd对象 * @exception IOException if an I/O error occurs. * @see java.io.FileDescriptor */ public final FileDescriptor getFD() throws IOException { if (fd != null) { return fd; } throw new IOException(); } /** * Returns the unique {@link java.nio.channels.FileChannel FileChannel} * object associated with this file input stream. * * <p> The initial {@link java.nio.channels.FileChannel#position() * position} of the returned channel will be equal to the * number of bytes read from the file so far. Reading bytes from this * stream will increment the channel's position. Changing the channel's * position, either explicitly or by reading, will change this stream's * file position. * * @return the file channel associated with this file input stream * * @since 1.4 * @spec JSR-51 */ public FileChannel getChannel() { FileChannel fc = this.channel; if (fc == null) { synchronized (this) { fc = this.channel; if (fc == null) { this.channel = fc = FileChannelImpl.open(fd, path, true, false, this); if (closed) { try { // possible race with close(), benign since // FileChannel.close is final and idempotent fc.close(); } catch (IOException ioe) { throw new InternalError(ioe); // should not happen } } } } } return fc; } }
FileOutputStream与FileInputStream基本相同
只是多了个构造方法 public FileOutputStream(String name, boolean append)来创建在文件末尾追加内容的输出流(默认是不追加,会导致文件原本内容被清除)。

浙公网安备 33010602011771号