尝尽悲欢离合人间苦
今天,我们来看下FileInputStream的内部结构
1.类结构
public
class FileInputStream extends InputStream
{
继承自InputStream抽象类,实现父类的所有抽象方法。
2.内部结构
构造函数
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
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.incrementAndGetUseCount();
this.path = name;
open(name);
}
final boolean isInvalid() {
if (status == null) {
status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
: PathStatus.INVALID;
}
return status == PathStatus.INVALID;
}
private native void open(String name) throws FileNotFoundException;
构造函数可以传入多种形式,String类型也是转化为File类型。
此处抛出了文件不存在异常,因此实例化的时候,需要加上try..catch或者在方法上抛出
异常,交给下一个调用者处理。
需要注意的是:第一,文件读取的时候还有权限检查的问题,类似于Linux下的文件访问权限。
第二,路径的合法性也需要判断;第三,先获取文件描述符对象
read方法
* @return the next byte of data, or <code>-1</code> if the end of the
* file is reached.
* @exception IOException if an I/O error occurs.
*/
public int read() throws IOException {
Object traceContext = IoTrace.fileReadBegin(path);
int b = 0;
try {
b = read0();
} finally {
IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
}
return b;
}
注意返回值是int类型,-1代表字节流结束,否则代表当前字节。
skip方法
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
* @exception IOException if n is negative, if the stream does not
* support seek, or if an I/O error occurs.
*/
public native long skip(long n) throws IOException;
available方法
* <p> In some cases, a non-blocking read (or skip) may appear to be
* blocked when it is merely slow, for example when reading large
* files over slow networks.
*
* @return an estimate of the number of remaining bytes that can be read
* (or skipped over) from this input stream without blocking.
* @exception IOException if this file input stream has been closed by calling
* {@code close} or an I/O error occurs.
*/
public native int available() throws IOException;
信道
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
* object associated with this file input stream.
*
* <p> The initial {@link java.nio.channels.FileChannel#position()
* </code>position<code>} of the returned channel will be equal to the
* number of bytes read from the file so far. Reading bytes from this
* stream will increment the channel's position. Changing the channel's
* position, either explicitly or by reading, will change this stream's
* file position.
*
* @return the file channel associated with this file input stream
*
* @since 1.4
* @spec JSR-51
*/
public FileChannel getChannel() {
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, path, true, false, this);
/*
* Increment fd's use count. Invoking the channel's close()
* method will result in decrementing the use count set for
* the channel.
*/
fd.incrementAndGetUseCount();
}
return channel;
}
}
属性
/* File Descriptor - handle to the open file */
private final FileDescriptor fd;
/* The path of the referenced file (null if the stream is created with a file descriptor) */
private final String path;
private FileChannel channel = null;
private final Object closeLock = new Object();
private volatile boolean closed = false;
private static final ThreadLocal<Boolean> runningFinalize =
new ThreadLocal<>();
文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。文件描述符的主要实际用途是创建一个包含该结构的 FileInputStream
或 FileOutputStream
。
path代表文件所在路径
channel代表NIO中的信道
closeLock代表
closed代表
runningFinalize代表