使用FileInputStream实现文件读取Demo:
package com.anbai.sec.filesystem;
import java.io.*;
/**
* Creator: yz
* Date: 2019/12/4
*/
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File("/etc/passwd");
// 打开文件对象并创建文件输入流
FileInputStream fis = new FileInputStream(file);
// 定义每次输入流读取到的字节数对象
int a = 0;
// 定义缓冲区大小
byte[] bytes = new byte[1024];
// 创建二进制输出流对象
ByteArrayOutputStream out = new ByteArrayOutputStream();
// 循环读取文件内容
while ((a = fis.read(bytes)) != -1) {
// 截取缓冲区数组中的内容,(bytes, 0, a)其中的0表示从bytes数组的
// 下标0开始截取,a表示输入流read到的字节数。
out.write(bytes, 0, a);
}
System.out.println(out.toString());
}
}
输出结果如下:
#
# User Database
#
# Note that this file is consulted directly only when the system is running
# in single-user mode. At other times this information is provided by
# Open Directory.
#
# See the opendirectoryd(8) man page for additional information about
# Open Directory.
#
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
.....内容过长省去多余内容
调用链如下:
java.io.FileInputStream.readBytes(FileInputStream.java:219)
java.io.FileInputStream.read(FileInputStream.java:233)
com.anbai.sec.filesystem.FileInputStreamDemo.main(FileInputStreamDemo.java:27)
其中的readBytes是native方法,文件的打开、关闭等方法也都是native方法:
private native int readBytes(byte b[], int off, int len) throws IOException;
private native void open0(String name) throws FileNotFoundException;
private native int read0() throws IOException;
private native long skip0(long n) throws IOException;
private native int available0() throws IOException;
private native void close0() throws IOException;
java.io.FileInputStream
类对应的native实现如下:
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
fileOpen(env, this, path, fis_fd, O_RDONLY);
}
JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read0(JNIEnv *env, jobject this) {
return readSingle(env, this, fis_fd);
}
JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,
jbyteArray bytes, jint off, jint len) {
return readBytes(env, this, bytes, off, len, fis_fd);
}
JNIEXPORT jlong JNICALL
Java_java_io_FileInputStream_skip0(JNIEnv *env, jobject this, jlong toSkip) {
jlong cur = jlong_zero;
jlong end = jlong_zero;
FD fd = GET_FD(this, fis_fd);
if (fd == -1) {
JNU_ThrowIOException (env, "Stream Closed");
return 0;
}
if ((cur = IO_Lseek(fd, (jlong)0, (jint)SEEK_CUR)) == -1) {
JNU_ThrowIOExceptionWithLastError(env, "Seek error");
} else if ((end = IO_Lseek(fd, toSkip, (jint)SEEK_CUR)) == -1) {
JNU_ThrowIOExceptionWithLastError(env, "Seek error");
}
return (end - cur);
}
JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_available0(JNIEnv *env, jobject this) {
jlong ret;
FD fd = GET_FD(this, fis_fd);
if (fd == -1) {
JNU_ThrowIOException (env, "Stream Closed");
return 0;
}
if (IO_Available(fd, &ret)) {
if (ret > INT_MAX) {
ret = (jlong) INT_MAX;
} else if (ret < 0) {
ret = 0;
}
return jlong_to_jint(ret);
}
JNU_ThrowIOExceptionWithLastError(env, NULL);
return 0;
}
完整代码参考OpenJDK:openjdk/src/java.base/share/native/libjava/FileInputStream.c