上一篇地址:赶紧收藏!2024 年最常见 100道 Java 基础面试题(七)-CSDN博客
十五、Java中IO流分为几种?
在Java中,IO(输入/输出)流是非常重要的概念,用于处理数据的输入和输出。Java的IO流可以分为以下几个主要类别:
-
基于数据类型分类:
- 字节流:处理二进制数据,以字节为单位进行读写。字节流的基类是
java.io.InputStream
和java.io.OutputStream
。 - 字符流:处理字符数据,以字符为单位进行读写,提供了对字符编码的自动转换。字符流的基类是
java.io.Reader
和java.io.Writer
。
- 字节流:处理二进制数据,以字节为单位进行读写。字节流的基类是
-
基于操作方式分类:
- 节点流(Low-level streams):直接操作节点数据,如文件、网络连接等。例如,
FileInputStream
、FileOutputStream
、SocketInputStream
和SocketOutputStream
。 - 包装流(Wrapper streams):在不改变节点流的情况下,对节点流进行包装,以提供额外的功能,如缓冲、数据转换等。例如,
BufferedReader
、BufferedWriter
、InputStreamReader
和OutputStreamWriter
。
- 节点流(Low-level streams):直接操作节点数据,如文件、网络连接等。例如,
-
基于操作特性分类:
- 阻塞IO:传统的IO操作,数据读写是同步的,必须等待IO操作完成,如
FileInputStream
和FileOutputStream
。 - 非阻塞IO(NIO):新IO,提供了非阻塞的数据读写能力,允许在读写操作等待时执行其他任务。NIO的核心是缓冲区(Buffer)和通道(Channel),如
FileChannel
、SocketChannel
和ServerSocketChannel
。 - 异步IO(AIO):在NIO的基础上进一步发展,提供了异步的IO操作,允许应用程序发起IO请求后立即返回,不必等待IO操作完成。Java 7引入了AIO的核心类
AsynchronousFileChannel
。
- 阻塞IO:传统的IO操作,数据读写是同步的,必须等待IO操作完成,如
-
基于流向分类:
- 输入流:用于读取数据,从源头(如文件、网络等)流向程序。
- 输出流:用于写入数据,从程序流向目的地(如文件、网络等)。
-
其他特殊流:
SequenceInputStream
:允许将多个输入流串联起来,像一个单一的流那样读取。PipedInputStream
和PipedOutputStream
:用于实现线程间的通信。
示例代码:
// 使用字节流读取文件
try (FileInputStream fis = new FileInputStream("file.txt")) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
// 处理读取的数据
}
}
// 使用字符流读取文件
try (FileReader reader = new FileReader("file.txt")) {
int i;
while ((i = reader.read()) != -1) {
// 处理读取的字符,i不是一个char,而是一个int,表示char的Unicode编码
}
}
// 使用缓冲流提高性能
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
// 处理读取的行
}
}
总结:
- Java IO流分为基于数据类型(字节流和字符流)、操作方式(节点流和包装流)、操作特性(阻塞IO、非阻塞IO、异步IO)和流向(输入流和输出流)等类别。
- 选择合适的流类型对于程序的性能和功能至关重要。
- Java IO和NIO提供了丰富的类和接口,以满足不同的IO操作需求。
十六、BIO
、NIO
、AIO
有什么区别?
BIO、NIO和AIO是Java中不同的IO(输入/输出)模型,它们各自有不同的特点和用途:
-
BIO(Blocking I/O)阻塞式IO:
- 在BIO模型中,当线程进行IO操作时,如果数据还没有准备好,它会被阻塞,直到数据准备完毕。
- 传统的BIO模型是简单且容易理解的,但它的主要问题是阻塞。这意味着在等待IO操作完成时,线程不能执行其他任务,这可能导致性能问题,特别是在需要同时处理大量并发请求的场景中。
-
NIO(Non-blocking I/O)非阻塞式IO:
- NIO是Java在1.4版本引入的一种新的IO模型,它提供非阻塞的IO操作。
- 在NIO模型中,所有的IO操作都是非阻塞的。这意味着当一个线程请求IO操作时,如果数据还没有准备好,它不会被阻塞,而是可以继续做其他工作。当数据准备完毕时,线程可以被通知来完成IO操作。
- NIO的核心组件包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。通道类似于流,但可以进行非阻塞操作。缓冲区用于存储数据,选择器用于监控多个通道的IO状态。
-
AIO(Asynchronous I/O)异步IO:
- AIO是Java在7.0版本引入的一种进一步的IO模型,它提供异步的IO操作。
- 在AIO模型中,IO操作是异步的,这意味着当线程发起IO请求后,不必等待IO操作完成,就可以去做其他事情。当IO操作完成时,系统会自动回调程序中定义的事件处理逻辑。
- AIO的核心是
AsynchronousSocketChannel
和AsynchronousServerSocketChannel
,它们允许应用程序发起异步IO请求,并通过CompletionHandler
接口来处理操作完成时的回调。
区别:
- 阻塞性:BIO是阻塞的,NIO是非阻塞的,而AIO是异步的。
- 使用场景:BIO适合于传统的、对性能要求不是特别高的场合;NIO适合于需要进行高速、大规模IO操作的场景;AIO适合于异步处理IO操作的场景,特别适用于连接数较多、连接时间较长的应用场景。
- 编程复杂度:BIO的编程模型比较简单,NIO的编程模型相对复杂,需要对缓冲区、通道和选择器有深刻的理解;AIO的编程模型进一步简化了IO操作,但牺牲了一定的控制性。
示例代码:
// BIO示例
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
// NIO示例
Path path = Paths.get("file.txt");
try (FileChannel fileChannel = FileChannel.open(path)) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (fileChannel.read(buffer) != -1) {
buffer.flip();
// 处理数据
buffer.clear();
}
}
// AIO示例(简化版,实际使用需要设置CompletionHandler)
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
fileChannel.read(buffer, 0);
总结:
- BIO、NIO和AIO各自有不同的特点和适用场景,它们提供了不同方式的IO操作,以满足不同的性能和编程需求。
- NIO和AIO相比于BIO,提供了非阻塞和异步的特性,有助于提高程序的并发能力和响应性。