前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >JDK源码:IO体系讲解

JDK源码:IO体系讲解

原创
作者头像
后台技术汇
修改2024-10-25 15:49:49
修改2024-10-25 15:49:49
12900
代码可运行
举报
文章被收录于专栏:后台技术汇后台技术汇
运行总次数:0
代码可运行

背景

IO流是Java中很重要的一部分内容,常用的数据传输,文件的上传和下载都和它分不开。

Java中的IO根据处理数据的方式,可以分为字节流和字符流,同时根据传输方向的不同,又可以分为输入流和输出流。

图片
图片

图中,整理了在Java 8中根据上述分类的IO流,其中字节输入流有28种,字节输出流有18种,字符输入流有9种,字符输出流有8种,看到这么多的流,实际开发中经常使用到的只是其中的一部分。

比如:

  • 字节输入流中的FileInputStream、BufferedInputStream,
  • 字节输出流中的FileOutputStream、BufferedOutputStream
  • 字符输入流中的BufferedReader、InputStreamReader、FileReader
  • 字符输出流中的BufferedWriter、OutputStreamWriter、FileWriter等。

在图中已用黑色框图进行了突出标注。

实战案例

1、输入流

1.1 FileInputStream

源码
代码语言:txt
复制

public class FileInputStream extends InputStream
{
    //【1】
    private final FileDescriptor fd;
    //【2】
    private final Object closeLock = new Object();
}

代码分析:

FileInputStream是Java IO中的一个类,用于从文件中读取数据。它继承自InputStream类,可以读取字节流。

  • FileInputStream可以打开一个文件,读取其中的数据,并将数据以字节流的形式返回。
  • 如果文件存在但是没有读取权限,FileInputStream会抛出SecurityException异常。
  • FileDescriptor 文件描述符
案例
代码语言:txt
复制

/**
 * 字节流-输入流-FileInputStream
 *
 */
public class FileInputStreamTest {
    public static void main(String[] args) throws IOException {
        File file = new File("/Users/bryantmo/Desktop/code/springcloud_test/webdoor/src/test/java/com/bryant/io/1.txt");
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] bytes = new byte[1024];
        int read = 0;
        // 直接从磁盘读入到内存
        while ((read = fileInputStream.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, read));
            // 可能再输出到磁盘持久化
        }
    }
}

1.2 ByteArrayInputStream

源码
代码语言:txt
复制

public class ByteArrayInputStream extends InputStream {

    protected byte buf[];

    protected int pos;
}

代码分析:

ByteArrayInputStream 提供了一个从字节数组输入数据的流。主要功能如下:

  • buf:存储字节数据的数组,其中buf[pos]表示下一个要读取的字节。
  • pos:记录当前读取位置的索引,保证非负且不大于数组长度。
案例
代码语言:txt
复制

/**
 * 输入流-字节流-ByteArrayInputStream
 */
@Slf4j
public class ByteArrayInputStreamTest {
    public static void main(String[] args) throws IOException {
        // 被读取的数据,内存
        byte[] bytes = "Hello world".getBytes();
        // ByteArrayInputStream 是 Java 中的一个类,它是 InputStream 的子类,用于从字节数组中读取数据。
        //这个类允许你将一个字节数组视为一个输入流,从而可以使用标准的 I/O 流操作来处理它。
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes, 0, 3);
        while (byteArrayInputStream.read() != -1) {
            byteArrayInputStream.read(bytes);
            log.info("byteArrayInputStream#read: data = {}", new String(bytes));
        }

    }
}

1.3 BufferedInputStream

源码
代码语言:txt
复制

public class BufferedInputStream extends FilterInputStream {
    private static int DEFAULT_BUFFER_SIZE = 8192;
    protected volatile byte[] buf;
    protected int count;
    protected int pos;
}

代码分析:

BufferedInputStream 是 FilterInputStream 的子类,用于对输入流进行缓冲处理。

缓冲输入流可以提高读取效率,因为它减少了与底层数据源的交互次数。

案例
代码语言:txt
复制

/**
 * 输入流-字节流-缓冲输入流
 */
@Slf4j
public class BufferedInputStreamTest {

    public static void main(String[] args) throws IOException {
        File file = new File("/Users/bryantmo/Desktop/code/springcloud_test/webdoor/src/test/java/com/bryant/io/1.txt");
        FileInputStream fileInputStream = new FileInputStream(file);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 2);
        // 设置一个内存
        byte[] bytes = new byte[3];
        int byteRead;
        while ((byteRead = bufferedInputStream.read()) != -1) {
            // 直接从磁盘读入数据到内存,非常慢
            int read = bufferedInputStream.read(bytes);
            log.info("read: data = {}, read = {}", new String(bytes), read);
        }
    }
}

1.4 BufferedReader

源码

代码语言:javascript
代码运行次数:0
复制
public class BufferedReader extends Reader {
    private Reader in;
    private char cb[];
}

代码分析:

BufferedReader该类实现了一个带缓冲区的字符输入流。

  • in:表示底层的字符输入流。
  • cb[]:字符缓冲区,用于存储读取的数据,提高读取效率
案例
代码语言:txt
复制
/**
 * 字符流-输入流-BufferedReader
 */
@Slf4j
public class BufferedReaderTest {
    public static void main(String[] args) throws IOException {
        File file = new File("/Users/bryantmo/Desktop/code/springcloud_test/webdoor/src/test/java/com/bryant/io/1.txt");
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            log.info("line : {}", line);
        }
    }
}

2、输出流

2.1 FileOutputStream

源码
代码语言:txt
复制
public class FileOutputStream extends OutputStream
{
    private final FileDescriptor fd;
}

代码分析:FileOutputStream类继承OutputStream

  • FileDescriptor fd,表示系统依赖的文件描述符,用于文件输出流操作。
案例

代码语言:txt
复制

/**
 * 字节流-输入流-FileOutputStream
 *
 */
public class FileOutputStreamTest {
    public static void main(String[] args) throws IOException {
        String data = "字节流-输入流-FileInputStream";
        // 文件标识符
        File file = new File("/Users/bryantmo/Desktop/code/springcloud_test/webdoor/src/test/java/com/bryant/io/1.txt");
        FileOutputStream fileInputStream = new FileOutputStream(file);
        // 直接从内存写入磁盘
        fileInputStream.write(data.getBytes());
        fileInputStream.flush();
    }
}

2.2 ByteArrayOutPutStream

源码
代码语言:txt
复制


public class ByteArrayOutputStream extends OutputStream {

    /**
     * The buffer where data is stored.
     */
    protected byte buf[];
    protected int count;
}

ByteArrayOutputStream的部分属性:

  • buf:一个受保护的字节数组,用于存储数据。
  • count:一个受保护的整型变量,记录已存储的数据量。
案例
代码语言:txt
复制

/**
 * 字节流-输出流-ByteArrayOutputStream
 */
@Slf4j
public class ByteArrayOutputStreamTest {
    public static void main(String[] args) throws IOException {
        String newString = "Hello, World!";
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 底层是for循环,写入ByteArrayOutputStream的内存数组
        baos.write(newString.getBytes());
        // 读出内存数组:底层会新建一个数组,通过数组拷贝,并返回
        byte[] bytes = baos.toByteArray();
        log.info("bytes: {}", bytes);
        log.info("string: {}", new String(bytes));
    }
}

2.3 BufferedOutputStream

源码

代码语言:txt
复制

public class BufferedOutputStream extends FilterOutputStream {
    /**
     * The internal buffer where data is stored.
     */
    protected byte buf[];
    protected int count;
}

BufferedOutputStream的部分属性:

  • buf:一个受保护的字节数组,用于内部缓冲存储数据。
  • count:一个受保护的整型变量,记录缓冲区中已存储的数据量
案例
代码语言:txt
复制

/**
 * 输出流-字节流-BufferedOutputStream
 * BufferedOutputStream通过内部维护一个缓冲区来减少对底层文件系统的调用次数,从而提高写入效率。
 */
@Slf4j
public class BufferedOutputStreamTest {
    public static void main(String[] args) throws IOException {
        // 设置一个内存数据
        String data = "Hello world...." + System.currentTimeMillis();
        // 输出流写入字符到磁盘
        File file = new File("/Users/bryantmo/Desktop/code/springcloud_test/webdoor/src/test/java/com/bryant/io/1.txt");
        FileOutputStream fileOutputStream = new FileOutputStream(file);

        // 这里我们测试了,缓冲区大小为2和222的预设值时,分别对应了底层不同的写入磁盘逻辑
//        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream, 2);
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream, 222);
        bufferedOutputStream.write(data.getBytes());
        // flush()方法用于强制将缓冲区中的数据写入到底层的文件输出流中。即使缓冲区未满,调用flush()也会立即执行写入操作。
        bufferedOutputStream.flush();
    }
}

2.4 BufferedWriter

源码
代码语言:txt
复制

public class BufferedWriter extends Writer {

    private Writer out;

    private char cb[];
}

BufferedWriter是 Java 中的一个类,用于高效地写入字符数据到文件或其他输出流。

它通过在内存中维护一个缓冲区来减少对底层资源的访问次数,从而提高写入性能。

主要特点
  1. 缓冲区机制:BufferedWriter 的核心优势在于其缓冲区机制。当你调用 write 方法时,数据首先被写入内存中的缓冲区,而不是直接写入底层输出流。只有当缓冲区满、显式调用 flush 方法或关闭流时,数据才会被写入底层输出流。这种机制减少了 I/O 操作的次数,从而提高了写入性能。

案例
代码语言:txt
复制

/**
 * 字符流-输出流-BufferedWriter
 */
@Slf4j
public class BufferedWriterTest {
    public static void main(String[] args) throws IOException {
        String data = "hello world";
        File file = new File("/Users/bryantmo/Desktop/code/springcloud_test/webdoor/src/test/java/com/bryant/io/2.txt");
        FileWriter fileWriter = new FileWriter(file);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        try {
            bufferedWriter.write(data);
            bufferedWriter.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 实战案例
    • 1、输入流
      • 1.1 FileInputStream
      • 1.2 ByteArrayInputStream
      • 1.3 BufferedInputStream
      • 1.4 BufferedReader
    • 2、输出流
      • 2.1 FileOutputStream
      • 2.2 ByteArrayOutPutStream
      • 2.3 BufferedOutputStream
      • 2.4 BufferedWriter
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档