[重学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();
}
});
}
}