使用FileInputStream实现文件读取Demo:

    1. package com.anbai.sec.filesystem;
    2. import java.io.*;
    3. /**
    4. * Creator: yz
    5. * Date: 2019/12/4
    6. */
    7. public class FileInputStreamDemo {
    8. public static void main(String[] args) throws IOException {
    9. File file = new File("/etc/passwd");
    10. // 打开文件对象并创建文件输入流
    11. FileInputStream fis = new FileInputStream(file);
    12. // 定义每次输入流读取到的字节数对象
    13. int a = 0;
    14. // 定义缓冲区大小
    15. byte[] bytes = new byte[1024];
    16. // 创建二进制输出流对象
    17. ByteArrayOutputStream out = new ByteArrayOutputStream();
    18. // 循环读取文件内容
    19. while ((a = fis.read(bytes)) != -1) {
    20. // 截取缓冲区数组中的内容,(bytes, 0, a)其中的0表示从bytes数组的
    21. // 下标0开始截取,a表示输入流read到的字节数。
    22. out.write(bytes, 0, a);
    23. }
    24. System.out.println(out.toString());
    25. }
    26. }

    输出结果如下:

    1. #
    2. # User Database
    3. #
    4. # Note that this file is consulted directly only when the system is running
    5. # in single-user mode. At other times this information is provided by
    6. # Open Directory.
    7. #
    8. # See the opendirectoryd(8) man page for additional information about
    9. # Open Directory.
    10. #
    11. nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
    12. root:*:0:0:System Administrator:/var/root:/bin/sh
    13. daemon:*:1:1:System Services:/var/root:/usr/bin/false
    14. .....内容过长省去多余内容

    调用链如下:

    1. java.io.FileInputStream.readBytes(FileInputStream.java:219)
    2. java.io.FileInputStream.read(FileInputStream.java:233)
    3. com.anbai.sec.filesystem.FileInputStreamDemo.main(FileInputStreamDemo.java:27)

    其中的readBytes是native方法,文件的打开、关闭等方法也都是native方法:

    1. private native int readBytes(byte b[], int off, int len) throws IOException;
    2. private native void open0(String name) throws FileNotFoundException;
    3. private native int read0() throws IOException;
    4. private native long skip0(long n) throws IOException;
    5. private native int available0() throws IOException;
    6. private native void close0() throws IOException;

    java.io.FileInputStream类对应的native实现如下:

    1. JNIEXPORT void JNICALL
    2. Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
    3. fileOpen(env, this, path, fis_fd, O_RDONLY);
    4. }
    5. JNIEXPORT jint JNICALL
    6. Java_java_io_FileInputStream_read0(JNIEnv *env, jobject this) {
    7. return readSingle(env, this, fis_fd);
    8. }
    9. JNIEXPORT jint JNICALL
    10. Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,
    11. jbyteArray bytes, jint off, jint len) {
    12. return readBytes(env, this, bytes, off, len, fis_fd);
    13. }
    14. JNIEXPORT jlong JNICALL
    15. Java_java_io_FileInputStream_skip0(JNIEnv *env, jobject this, jlong toSkip) {
    16. jlong cur = jlong_zero;
    17. jlong end = jlong_zero;
    18. FD fd = GET_FD(this, fis_fd);
    19. if (fd == -1) {
    20. JNU_ThrowIOException (env, "Stream Closed");
    21. return 0;
    22. }
    23. if ((cur = IO_Lseek(fd, (jlong)0, (jint)SEEK_CUR)) == -1) {
    24. JNU_ThrowIOExceptionWithLastError(env, "Seek error");
    25. } else if ((end = IO_Lseek(fd, toSkip, (jint)SEEK_CUR)) == -1) {
    26. JNU_ThrowIOExceptionWithLastError(env, "Seek error");
    27. }
    28. return (end - cur);
    29. }
    30. JNIEXPORT jint JNICALL
    31. Java_java_io_FileInputStream_available0(JNIEnv *env, jobject this) {
    32. jlong ret;
    33. FD fd = GET_FD(this, fis_fd);
    34. if (fd == -1) {
    35. JNU_ThrowIOException (env, "Stream Closed");
    36. return 0;
    37. }
    38. if (IO_Available(fd, &ret)) {
    39. if (ret > INT_MAX) {
    40. ret = (jlong) INT_MAX;
    41. } else if (ret < 0) {
    42. ret = 0;
    43. }
    44. return jlong_to_jint(ret);
    45. }
    46. JNU_ThrowIOExceptionWithLastError(env, NULL);
    47. return 0;
    48. }

    完整代码参考OpenJDK:openjdk/src/java.base/share/native/libjava/FileInputStream.c