java FileInputStream open0源码解析
java FileInputStream源码
本文的jdk源码为openjdk1.8。在java中对File类来表示文件,但是File类并没有inputStream和outputStream来对文件输入输出进行操作,在java中文件的输入输出功能交由FileInputStream和FileOutputStream两个类来进行。
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);
}
/**
* Opens the specified file for reading.
* @param name the name of the file
*/
private void open(String name) throws FileNotFoundException {
open0(name);
}
/**
* Opens the specified file for reading.
* @param name the name of the file
*/
private native void open0(String name) throws FileNotFoundException;
FileInputStream构造函数通过输入File来进行构造,其中的file通过open来打开,open方法通过调用open0来运行打开方法,open0是native方法。
open0的方法定义在openjdk\jdk\src\share\native\java\io\FileInputStream.c中
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
fileOpen(env, this, path, fis_fd, O_RDONLY);
}
windows环境下fileOpen函数在openjdk\jdk\src\windows\native\java\io\io_util_md.c中
void
fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
{
FD h = winFileHandleOpen(env, path, flags);
if (h >= 0) {
SET_FD(this, h, fid);
}
}
FD
winFileHandleOpen(JNIEnv *env, jstring path, int flags)
{
const DWORD access =
(flags & O_WRONLY) ? GENERIC_WRITE :
(flags & O_RDWR) ? (GENERIC_READ | GENERIC_WRITE) :
GENERIC_READ;
const DWORD sharing =
FILE_SHARE_READ | FILE_SHARE_WRITE;
const DWORD disposition =
/* Note: O_TRUNC overrides O_CREAT */
(flags & O_TRUNC) ? CREATE_ALWAYS :
(flags & O_CREAT) ? OPEN_ALWAYS :
OPEN_EXISTING;
const DWORD maybeWriteThrough =
(flags & (O_SYNC | O_DSYNC)) ?
FILE_FLAG_WRITE_THROUGH :
FILE_ATTRIBUTE_NORMAL;
const DWORD maybeDeleteOnClose =
(flags & O_TEMPORARY) ?
FILE_FLAG_DELETE_ON_CLOSE :
FILE_ATTRIBUTE_NORMAL;
const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;
HANDLE h = NULL;
WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE);
if (pathbuf == NULL) {
/* Exception already pending */
return -1;
}
h = CreateFileW(
pathbuf, /* Wide char path name */
access, /* Read and/or write permission */
sharing, /* File sharing flags */
NULL, /* Security attributes */
disposition, /* creation disposition */
flagsAndAttributes, /* flags and attributes */
NULL);
free(pathbuf);
if (h == INVALID_HANDLE_VALUE) {
throwFileNotFoundException(env, path);
return -1;
}
return (jlong) h;
}
在fileOpen方法中主要是调用winFileHandleOpen方法,通过该方法返回的Handle来判断是否打开成功,如果成功就对FD(fileDescription文件描述符)进行设置,如果不存在失败则字节返回。在winFileHandleOpen中通过flag来判断文件打开后的权限。在winFileHandleOpen中通过对flag的一系列权限的判断来确定文件的权限,在Java_java_io_FileInputStream_open0中设置文件为O_RDONLY,在winFileHandleOpen中文件以GENERIC_READ权限打开,GENERIC_READ表示允许对设备(文件)进行读访问。最后通过SET_FD()将文件的句柄进行保存到调用该方法的对象中,就是java中FileDescriptor类的fd,用于后面的文件的操作。