[重学Java基础][Java IO流][Part.14]文件字节输入输出流

[重学Java基础][Java IO流][Part.14]文件字节输入输出流

FileInputStream

概述

FileInputStream 是文件输入流,继承了InputStream 是InputStream 的一个包装流
作用是读入File类型文件到内存进行处理

源码解析

成员函数

    文件描述符 实际上是文件的指针 调用系统接口
    private final FileDescriptor fd;
    文件路径
    private final String path;
    文件读入的通道
    private volatile FileChannel channel;
    锁对象 用于保证线程安全
    private final Object closeLock = new Object();
    流关闭标志
    private volatile boolean closed;

成员方法

构造方法

    传入路径名构造一个FileInputStream
    实际内部调用了第二个构造方法
    public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }

    传入文件对象构造一个FileInputStream
    public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        安全检查
        if (security != null) {
            security.checkRead(name);
        }
        路径为空抛空指针异常
        if (name == null) {
            throw new NullPointerException();
        }
        路径不合法 抛文件未找到异常
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        创造一个文件描述符 映射到磁盘上的文件
        fd = new FileDescriptor();
        fd.attach(this);
        path = name;
        按照路径打开文件
        open(name);
    }

    传入文件描述符对象构造一个FileInputStream
    public FileInputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        }
        if (security != null) {
            security.checkRead(fdObj);
        }
        fd = fdObj;
        path = null;

        fd.attach(this);
    }

其他方法

打开文件方法

    内部调用open0()方法
    private void open(String name) throws FileNotFoundException {
        open0(name);
    }
    本地方法 显然是调用系统API的方法
    private native void open0(String name) throws FileNotFoundException;

读取 跳过 可用方法 都是本地方法

    public int read() throws IOException {
            return read0();
        }
    也是本地方法
    private native int read0() throws IOException;

    private native int readBytes(byte[] var1, int var2, int var3) throws IOException;

    public int read(byte[] b) throws IOException {
        return this.readBytes(b, 0, b.length);
    }

    public int read(byte[] b, int off, int len) throws IOException {
        return this.readBytes(b, off, len);
    }

    public long skip(long n) throws IOException {
        return this.skip0(n);
    }

    private native long skip0(long var1) throws IOException;

    public int available() throws IOException {
        return this.available0();
    }

    private native int available0() throws IOException;

关闭方法

public void close() throws IOException {
        if (!this.closed) {
            Object var1 = this.closeLock;
            关闭标志位置为true
            synchronized(this.closeLock) {
                if (this.closed) {
                    return;
                }

                this.closed = true;
            }
            关闭通道
            FileChannel fc = this.channel;
            if (fc != null) {
                fc.close();
            }
            文件描述符关闭
            this.fd.closeAll(new Closeable() {
                public void close() throws IOException {
                    FileInputStream.this.close0();
                }
            });
        }
    }
真正的关闭方法 是本地方法
private native void close0() throws IOException;

FileOutputStream

概述

FileOutputStream是文件输出流 继承了OutputStream是OutputStream的一个包装流
用于输出文件到外部

源码解析

成员函数

    文件访问许可
    private static final JavaIOFileDescriptorAccess fdAccess =
        SharedSecrets.getJavaIOFileDescriptorAccess();

    文件描述符
    private final FileDescriptor fd;

    文件访问通道
    private volatile FileChannel channel;

    文件路径
    private final String path;

    锁对象
    private final Object closeLock = new Object();

    关闭标志
    private volatile boolean closed;

成员方法

构造方法

    根据路径创建FileOutputStream对象
    public FileOutputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null, false);
    }

    根据路径创建FileOutputStream对象 并且设定是否从尾部写入 append为true则从文件尾部开始写入
    public FileOutputStream(String name, boolean append) throws FileNotFoundException {
        this(name != null ? new File(name) : null, append);
    }

    根据文件对象创建FileOutputStream对象
    public FileOutputStream(File file) throws FileNotFoundException {
        this(file, false);
    }

    根据文件对象和是否尾部追加写入创建输出流 
    真正的构造方法 前面都构造方法都是快捷方法
    public FileOutputStream(File file, boolean append) throws FileNotFoundException {
        this.closeLock = new Object();
        String name = file != null ? file.getPath() : null;
        安全检查
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(name);
        }
        初始化成员
        if (name == null) {
            throw new NullPointerException();
        } else if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        } else {
            this.fd = new FileDescriptor();
            this.fd.attach(this);
            this.path = name;
            this.open(name, append);
        }
    }

    根据文件描述符对象写入创建输出流 
    public FileOutputStream(FileDescriptor fdObj) {
        this.closeLock = new Object();
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        } else {
            if (security != null) {
                security.checkWrite(fdObj);
            }

            this.fd = fdObj;
            this.path = null;
            this.fd.attach(this);
        }
    }

其他方法 都是本地方法

    打开文件方法
    private void open(String name, boolean append) throws FileNotFoundException {
        this.open0(name, append);
    }

    private native void open0(String var1, boolean var2) throws FileNotFoundException;

    写入单字节方法 内部调用本地方法
    private native void write(int var1, boolean var2) throws IOException;

    public void write(int b) throws IOException {
        this.write(b, fdAccess.getAppend(this.fd));
    }

    写入多字节方法 内部调用本地方法
    public void write(byte[] b) throws IOException {
        this.writeBytes(b, 0, b.length, fdAccess.getAppend(this.fd));
    }

    public void write(byte[] b, int off, int len) throws IOException {
        this.writeBytes(b, off, len, fdAccess.getAppend(this.fd));
    }

    private native void writeBytes(byte[] b, int off, int len, boolean append) throws IOException;

    关闭方法
    public void close() throws IOException {
        if (!this.closed) {
            Object var1 = this.closeLock;
            synchronized(this.closeLock) {
                if (this.closed) {
                    return;
                }

                this.closed = true;
            }

            FileChannel fc = this.channel;
            if (fc != null) {
                fc.close();
            }

            this.fd.closeAll(new Closeable() {
                public void close() throws IOException {
                    FileOutputStream.this.close0();
                }
            });
        }
    }

猜你喜欢

转载自blog.csdn.net/u011863951/article/details/80378975