大家好,又见面了,我是你们的朋友全栈君。
我们先写个简单的Demo,代码如下:
package com.lg.io;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("src\\com\\lg\\io\\FileInputStreamDemo.java");
byte[] buf=new byte[1024];
int n;
while ((n=fis.read(buf))>0){
System.out.print(new String(buf,0,n));
}
fis.close();
}
}
上面的Demo是读取自己的内容,运行结果如下:
package com.lg.io;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("src\\com\\lg\\io\\FileInputStreamDemo.java");
byte[] buf=new byte[1024];
int n;
while ((n=fis.read(buf))>0){
System.out.print(new String(buf,0,n));
}
fis.close();
}
}
接着FileInputStream源码分析,如下:
属性
// 文件描述类,处理打开的文件
private final FileDescriptor fd;
// 文件的路径,如果该流是通过文件描述类创建的,该属性则为空
private final String path;
// 用于读、写、映射、操作文件的通道
private FileChannel channel = null;
// 一个关闭锁,只在close()方法中使用,确保多线程同步调用,同时和其他同步方法不冲突(因为这个关
//闭锁是自己的对象锁)
private final Object closeLock = new Object();
// 流是否是关闭的,volatile保证多线程的可见性
private volatile boolean closed = false;
构造函数
// 文件路径创建File对象,并调用下边的重载的构造函数
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
// 根据File对象来构造文件输入流
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) {
// 文件路径为null,抛出空指针异常
throw new NullPointerException();
}
if (file.isInvalid()) {
// 如果file对象无效,抛出未找到文件异常
throw new FileNotFoundException("Invalid file path");
}
// 创建文件描述符
fd = new FileDescriptor();
// 在文件描述符中保存该对象引用
fd.attach(this);
// 路径名赋值path
path = name;
// 打开该路径进行读取
open(name);
}
// 根据文件描述符构造输入流
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);
}
方法
open(String name)
// 调用open0(name)本地方法,打开指定的文件以进行读取
private void open(String name) throws FileNotFoundException {
open0(name);
}
//打开指定的文件以进行读取
private native void open0(String name) throws FileNotFoundException;
read()
// 从输入流中读取下一个字节的数据,调用本地方法
// 该方法一直阻塞直到有可用的数据
public int read() throws IOException {
return read0();
}
// 本地方法,读取下一个字节的数据
private native int read0() throws IOException;
read(byte b[])
// 读取b.length数量的字节,并从字节数组b的0下标开始填满b数组
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
// 读取b.length数量的字节,并从字节数组b的off下标位置开始填满b数组
public int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}
// 本地方法,将子数组作为字节序列读取
private native int readBytes(byte b[], int off, int len) throws IOException;
Native方法
// 本地方法,跳过n个字节
public native long skip(long n) throws IOException;
// 本地方法,返回可读的字节数
public native int available() throws IOException;
close()
public void close() throws IOException {
// 使用对象锁
synchronized (closeLock) {
// 如果流已经关闭则返回
if (closed) {
return;
}
// 否则将关闭状态设为true
closed = true;
}
// 操作文件的通道不为空,也要进行关闭
if (channel != null) {
channel.close();
}
// 文件描述符相关资源的关闭,并调用本地关闭方法关闭流
fd.closeAll(new Closeable() {
public void close() throws IOException {
close0();
}
});
}
//本地方法,关闭此文件输入流并释放与该流关联的所有系统资源
private native void close0() throws IOException;
finalize()
protected void finalize() throws IOException {
if ((fd != null) && (fd != FileDescriptor.in)) {
// 如果fd正在被其他流使用,就不能进行关闭,只有当所有流都不再引用这个文件描述符才关闭
close();
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132020.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...