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