java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java IO和NIO的基本概念和API

Java IO和NIO的基本概念和API详解

作者:冰糖心书房

JavaIO是基于流的阻塞式I/O,适用于低并发场景;JavaNIO是基于通道和缓冲区的非阻塞式I/O,适用于高并发场景

一、 Java IO (Blocking IO)

基本概念

IO 流的分类

按数据传输方向:

按数据传输单位:

核心类和接口

InputStream (字节输入流):

OutputStream (字节输出流):

Reader (字符输入流):

Writer (字符输出流):

IO 操作流程 (以读取文件为例)

  1. 创建 File 对象: 指定要读取的文件路径。
  2. 创建 FileInputStream 对象:File 对象作为参数传递给 FileInputStream 的构造方法,创建一个 FileInputStream 对象。
  3. 创建 BufferedInputStream 对象 (可选):FileInputStream 对象作为参数传递给 BufferedInputStream 的构造方法,创建一个 BufferedInputStream 对象,提高读取效率。
  4. 读取数据: 使用 read() 方法从输入流中读取数据。
  5. 关闭流: 在完成读取操作后,务必关闭输入流,释放资源(先关闭 BufferedInputStream,再关闭 FileInputStream)。

代码示例 (读取文件内容):

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class IOExample {
    public static void main(String[] args) {
        File file = new File("test.txt"); // 替换为你的文件路径

        try (FileInputStream fis = new FileInputStream(file);
             BufferedInputStream bis = new BufferedInputStream(fis)) { // 使用 try-with-resources 语句,自动关闭流

            byte[] buffer = new byte[1024];
            int bytesRead;

            while ((bytesRead = bis.read(buffer)) != -1) {
                // 处理读取到的数据
                String data = new String(buffer, 0, bytesRead);
                System.out.print(data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二、 Java NIO (Non-blocking IO)

基本概念

核心组件

通道 (Channel):

缓冲区 (Buffer):

选择器 (Selector):

NIO 操作流程 (以读取 SocketChannel 数据为例)

  1. 创建 ServerSocketChannel 监听客户端连接。
  2. 创建 SocketChannel 接受客户端连接。
  3. SocketChannel 注册到 Selector 指定要监听的事件(例如 OP_READ, OP_WRITE, OP_CONNECT, OP_ACCEPT)。
  4. 创建 ByteBuffer 用于存储读取到的数据。
  5. 调用 selector.select() 方法: 阻塞等待有事件发生的通道。
  6. 获取就绪的通道: selector.selectedKeys() 返回所有就绪通道的集合。
  7. 处理事件: 遍历就绪通道的集合,根据不同的事件类型执行相应的操作(例如读取数据、写入数据)。
  8. 读取数据: 调用 channel.read(buffer) 从通道读取数据到缓冲区。
  9. 处理缓冲区数据: 从缓冲区读取数据并进行处理。
  10. 关闭通道和选择器: 在完成操作后,务必关闭通道和选择器,释放资源。

代码示例 (使用 SocketChannel 读取数据):

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NIOExample {
    public static void main(String[] args) throws IOException {
        // 1. 创建 SocketChannel
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("www.example.com", 80));
        socketChannel.configureBlocking(false); // 设置为非阻塞模式

        // 2. 创建 ByteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        // 3. 从 Channel 读取数据到 Buffer
        int bytesRead = socketChannel.read(buffer);

        while (bytesRead > 0) {
            // 切换到读模式
            buffer.flip();

            // 4. 从 Buffer 读取数据
            while (buffer.hasRemaining()) {
                System.out.print((char) buffer.get());
            }

            // 清空 Buffer,准备下一次读取
            buffer.clear();
            bytesRead = socketChannel.read(buffer);
        }

        socketChannel.close();
    }
}

三、 Java IO 与 NIO 的区别

特性Java IO (Blocking IO)Java NIO (Non-blocking IO)
数据传输方式基于流 (Stream)基于通道 (Channel) 和缓冲区 (Buffer)
I/O 模型阻塞式 I/O (Blocking I/O)非阻塞式 I/O (Non-blocking I/O)
选择器没有有 (Selector)
API简单易用相对复杂,需要理解通道、缓冲区、选择器等概念
性能性能较低 (高并发下)性能较高 (高并发下)
线程模型通常使用多线程模型 (每个连接一个线程)通常使用单线程多路复用模型 (一个线程管理多个连接)
适用场景低并发、连接数较少的应用,或者可以接受阻塞的场景高并发、连接数较多的应用,需要高性能和非阻塞的场景,例如网络服务器、聊天服务器等

四、 选择哪种 I/O 模式?

总结

Java IO 和 NIO 都是 Java 平台提供的用于进行输入和输出操作的 API。

Java IO 基于流的模型,使用简单但性能较低; Java NIO 基于通道和缓冲区的模型,提供高性能、非阻塞的 I/O 操作。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文