一、IO体系的核心概念
1.什么是IO
Java应用程序与外部环境(如文件系统、网络等)之间的数据交换。
2.流
(1)什么是
- 数据传输的抽象体现
3. 类型
(1)字节流
- 以字节为单位处理数据,主要处理原始二进制数据,比如说图像、声音。
- 主要类包含InputStream和OutputStream。
(2)字符流
- 以字符为单位处理数据,适用于处理文本处理。
- 主要类包含Reader和Writer。
二、主要类和接口
1.InputStream/Reader:所有输入流的基类。InputStream是字节输入流,Reader是字符输入流。
2.OutputStream/Writer:所有输出流的基类。OutputStream是字节输出流,Writer是字符输出流。
3.File:用于表示文件和目录路径名的抽象表示形式。
4.RandomAccessFile:允许对文件的任何位置进行读写操作。
三 、详细分类
1.按流向分类
- 输入流:用于从数据源读取数据。例如,从文件中读取内容等操作都会用到输入流。
- 输出流:用于将数据写入到目的地。比如把数据写入文件等操作需要使用输出流。
2.按数据处理方式分类
- 字节流:以字节为单位进行数据的读写操作。字节流可以处理任何类型的数据,因为所有的数据在计算机底层都是以字节的形式存储的。
- 例如,读取或写入二进制文件(如图像文件、音频文件等)、进行网络字节数据传输等都需要使用字节流。
- 字符流:以字符为单位进行读写操作。字符流主要用于处理文本数据,它会根据字符编码(如UTF-8、GBK等)将字符转换为字节进行存储或传输。
- 例如,在处理文本文件(如.txt文件)、读取配置文件等场景中非常有用。
3.按常用流类分类
- FileInputStream/FileOutputStream:用于从文件读取字节或向文件写入字节。
- FileReader/FileWriter:用于从文件读取字符或向文件写入字符。
- BufferedInputStream/BufferedOutputStream:为字节输入/输出流添加缓冲功能。
- BufferedReader/BufferedWriter:为字符输入/输出流添加缓冲功能。
- DataInputStream/DataOutputStream:允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型和字符串,或将这些数据写入输出流中。
四、高级操作
1.缓冲流
- 使用缓冲流可以减少实际的读写操作次数,从而提高性能。
- Java IO提供了BufferedInputStream、BufferedOutputStream、BufferedReader和BufferedWriter等缓冲流类。
2.转换流
- InputStreamReader和OutputStreamWriter是字符流和字节流之间的桥梁。
- 它们分别用于将字节输入流转为字符输入流,将字符输出流转为字节输出流。
- 在处理文本数据时,需要指定正确的字符编码,以避免出现乱码问题。
3.序列化流
- ObjectInputStream和ObjectOutputStream允许将Java对象序列化为字节流,或从字节流中反序列化出Java对象。
- 这对于对象的持久化存储和网络传输非常有用。
五、最佳实践
1.使用try-with-resources语句:自动管理资源,确保流在使用完毕后能够正确关闭,避免资源泄露。
2.选择合适的字符编码:在处理文本数据时,需要指定正确的字符编码,以避免出现乱码问题。
3.使用缓冲流提高性能:对于大文件或频繁的IO操作,使用缓冲流可以显著提高性能。
4.注意异常处理:IO操作可能会抛出IOException,需要通过try-catch块进行捕获和处理。
六、其他知识点
1.节点流与处理流
- 节点流:直接从数据源或目的地读写数据。例如,FileInputStream和FileOutputStream就是节点流,它们直接从文件中读写数据。
- 处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。例如,BufferedInputStream和BufferedOutputStream就是处理流,它们为节点流提供了缓冲功能。
2.流的链接
- 一个流对象可以经过其他流的多次包装,形成流的链接。这样,可以通过多个处理流对数据进行多次处理。
3.NIO(New IO)
(1)什么是
- Java NIO是Java 1.4及后续版本引入的一个新的IO API,它提供了与标准IO不同的IO工作方式。
- NIO是基于通道(Channel)和缓冲区(Buffer)的IO方式,它可以使用非阻塞IO操作,这对于高性能的网络应用程序来说非常有用。
(2) 相关术语
- Buffer:缓冲区,用于存储数据。
- Channel:通道,用于读写数据。
- Selector:选择器,用于多路复用I/O操作。
- ByteBuffer:字节缓冲区,支持读写操作。
- FileChannel:文件通道,用于文件的读写操作。
- SocketChannel:套接字通道,用于网络通信。
4. 序列化与反序列化
- 序列化:将对象的状态信息转换为可以存储或传输的形式的过程。在Java中,可以通过实现Serializable接口来使对象可序列化。
- 反序列化:将序列化后的对象状态信息恢复为对象的过程。
七、面试常考的八股文
1.Java IO流分为哪两大类?它们之间的主要区别是什么?
- Java IO流分为字节流和字符流。
- 字节流以字节为单位处理数据,适用于处理二进制数据;字符流以字符为单位处理数据,适用于处理文本数据。
2.请解释节点流和处理流的区别。
- 节点流直接从数据源或目的地读写数据,如FileInputStream和FileOutputStream;
- 处理流不直接连接到数据源或目的地,而是“连接”在已存在的流之上,通过对数据的处理为程序提供更为强大的读写功能,如BufferedInputStream和BufferedOutputStream。
3.什么是流的链接?在Java中如何实现流的链接?
- 流的链接是指一个流对象经过其他流的多次包装。
- 在Java中,可以通过将多个处理流连接到一个节点流上来实现流的链接。例如,可以将BufferedInputStream和DataInputStream连接到一个FileInputStream上,以实现对文件的缓冲和按数据类型读取。
4.请解释Java NIO中的Channel和Buffer的作用,以及它们与标准IO的区别。
- Channel是一个连接到数据源或目的地的通道,可以读取数据到Buffer中或将Buffer中的数据写入到数据源或目的地。
- Buffer是一个内存块,用于临时存储数据。
- 与标准IO相比,NIO基于Channel和Buffer的IO方式更加灵活和高效,支持非阻塞IO操作。
5.请解释Java中的序列化与反序列化,并给出实现序列化的步骤。
- 序列化是将对象的状态信息转换为可以存储或传输的形式的过程;
- 反序列化是将序列化后的对象状态信息恢复为对象的过程。在Java中,可以通过实现Serializable接口来使对象可序列化
- 实现序列化的步骤包括:将需要序列化的类实现Serializable接口(无需实现任何方法),然后使用一个输出流(如FileOutputStream)来构造一个ObjectOutputStream对象,并通过该对象的writeObject()方法将对象写入到输出流中。
6.如何处理大文件的读写?
- 处理大文件时,可以使用缓冲流(如BufferedInputStream和BufferedOutputStream)来提高读写效率。对于非常大的文件,还可以考虑使用NIO中的FileChannel和MappedByteBuffer进行内存映射。
7.在使用 IO 流时,如何有效地捕获和处理异常?
在使用 IO 流时,应该使用 try-catch-finally 语句块来捕获和处理可能发生的异常。具体做法如下:
- 在 try 块中编写使用 IO 流的代码。
- 在 catch 块中捕获可能发生的 IOException 及其子类异常,并进行相应的处理,如打印异常信息、释放资源等。
- 在 finally 块中释放 IO 流所占用的资源,如关闭文件、网络连接等。这可以确保无论是否发生异常,资源都能得到正确的释放。