FileInputStream 源码分析

java.io.FileInputStream是从文件系统中获取一个文件的原始字节。如果要读取字符流,可以用java.io.FileReader。


public class FileInputStream extends InputStream {

private FileDescriptor fd;

private FileChannel channel = null;

// 调用参数为File的构造函数
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}

// 获取文件的路径并检查权限
// 实例化FileDescriptor并赋给fd
// 打开文件(native方法)
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();
}
fd = new FileDescriptor();
open(name);
}

// 检查权限和输入是否为空
// 把参数对象赋给fd
public FileInputStream(FileDescriptor fdObj) {
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
throw new NullPointerException();
}
if (security != null) {
security.checkRead(fdObj);
}
fd = fdObj;
}

// 根据文件名打开指定的文件
private native void open(String name) throws FileNotFoundException;

// 读取1个字节的数据,如果没有输入,则该方法阻断
public native int read() throws IOException;

// 从off位置开始,读取len长度字节的数据到字节数组b中
private native int readBytes(byte b[], int off, int len) throws IOException;

// 读取所有的字节到字节数组b中,如果输入不可用,则该方法阻断
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}

// 读取len长度的字节到字节数组b中,如果len不为0并且输入不可用,则该方法阻断,如果为0则返回0
public int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}

// 从输入流中跳过并丢弃 n 个字节的数据。
//出于各种原因,skip 方法最终跳过的字节数可能更少一些,甚至可能为 0。如果 n 为负,则抛出 IOException,即使 InputStream 超类的 skip 方法在这种情况下没有执行任何操作。返回实际跳过的字节数。
//此方法跳过的字节可能多于底层文件中剩余的字节。这不会产生异常,并且跳过的字节数可能包括底层文件的 EOF(文件结束符)之后的一些字节数。如果试图在跳过末尾之后读取流,那么会返回指示文件末尾的 -1。
public native long skip(long n) throws IOException;

// 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。
// 在某些情况下,非阻塞的读取(或跳过)操作在执行很慢时看起来受阻塞,例如,在网速缓慢的网络上读取大文件时
public native int available() throws IOException;

// 关闭流并且释放所有和这个流关联的系统资源
public void close() throws IOException {
if (channel != null)
channel.close();
close0();
}

// 返回表示到文件系统中实际文件的连接的FileDescriptor对象,该文件正被当前的FileInputStream实例所使用
public final FileDescriptor getFD() throws IOException {
if (fd != null) return fd;
throw new IOException();
}

// 返回和这个流关联的唯一FileChannel对象
// 返回的文件通道的初始位置和从文件中当前读取的字节数相等。从这个流中读取字节会让通道的位置增加。改变通道的位置,通过显式的的或者读取,会改变流的文件位置。
public FileChannel getChannel() {
synchronized (this) {
if (channel == null)
channel = FileChannelImpl.open(fd, true, false, this);
return channel;
}
}

private static native void initIDs();

private native void close0() throws IOException;

static {
initIDs();
}

// 确保没有对象和当前流关联时,调用close()方法来释放资源
protected void finalize() throws IOException {
if (fd != null) {
if (fd != fd.in) {
close();
}
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值