Java IO流与NIO终极指南:从基础到高级应用

一、IO流与NIO概述

1.1 什么是IO流

IO(Input/Output)流是Java中用于处理输入输出的核心机制,它像水流一样将数据从源头(如文件、网络连接等)传输到目的地。Java IO流主要分为字节流和字符流两大类。

通俗理解:想象IO流就像水管,数据就是水流。字节流是原始的水流(二进制数据),字符流则是经过处理的可直接饮用的水(文本数据)。

1.2 IO与NIO的区别

特性 IO (传统IO) NIO (New IO)
数据流动方式 流式(Stream) 块式(Channel和Buffer)
缓冲机制 大多数操作无缓冲 总是使用Buffer
阻塞/非阻塞 阻塞式(Blocking) 可选择非阻塞(Non-blocking)
选择器(Selector) 无 有
适用场景 连接数较少,数据传输量大的情况 连接数多,每个连接数据传输量小的情况

通俗理解:传统IO就像单线程的餐厅服务员,一次只能服务一桌客人;NIO则像多线程服务员,可以同时照看多桌客人,哪桌有需求就去服务哪桌。

二、Java IO流体系

2.1 IO流分类

Java IO流可以按照以下维度分类:

  1. 按数据单位:

    • 字节流(8位字节):InputStream/OutputStream
    • 字符流(16位Unicode字符):Reader/Writer
  2. 按流向:

    • 输入流:从数据源读取数据
    • 输出流:向目的地写入数据
  3. 按功能:

    • 节点流:直接与数据源连接
    • 处理流:对节点流进行包装,提供额外功能

2.2 核心类继承体系

字节流体系
复制代码
InputStream (抽象类)
├─ FileInputStream
├─ FilterInputStream
│  ├─ BufferedInputStream
│  ├─ DataInputStream
│  └─ PushbackInputStream
├─ ObjectInputStream
├─ PipedInputStream
├─ ByteArrayInputStream
└─ SequenceInputStream

OutputStream (抽象类)
├─ FileOutputStream
├─ FilterOutputStream
│  ├─ BufferedOutputStream
│  ├─ DataOutputStream
│  └─ PrintStream
├─ ObjectOutputStream
├─ PipedOutputStream
└─ ByteArrayOutputStream
字符流体系
复制代码
Reader (抽象类)
├─ BufferedReader
├─ InputStreamReader
│  └─ FileReader
├─ StringReader
├─ PipedReader
└─ CharArrayReader

Writer (抽象类)
├─ BufferedWriter
├─ OutputStreamWriter
│  └─ FileWriter
├─ StringWriter
├─ PipedWriter
└─ CharArrayWriter

2.3 常用IO流方法详解

InputStream核心方法
方法签名 描述 返回值说明
int read() 读取一个字节 返回读取的字节(0-255),如果到达末尾返回-1
int read(byte[] b) 读取最多b.length个字节到数组 返回实际读取的字节数,末尾返回-1
int read(byte[] b, int off, int len) 读取最多len个字节到数组的off位置 同上
long skip(long n) 跳过并丢弃n个字节 返回实际跳过的字节数
int available() 返回可读取的估计字节数 通常用于检查是否可无阻塞读取
void close() 关闭流并释放资源 无
boolean markSupported() 是否支持mark/reset 返回布尔值
void mark(int readlimit) 标记当前位置 无
void reset() 重置到最后一次mark的位置 无
OutputStream核心方法
方法签名 描述 返回值说明
void write(int b) 写入一个字节 无
void write(byte[] b) 写入整个字节数组 无
void write(byte[] b, int off, int len) 写入字节数组的一部分 无
void flush() 强制刷新输出缓冲区 无
void close() 关闭流并释放资源 无
Reader核心方法
方法签名 描述 返回值说明
int read() 读取一个字符 返回读取的字符(0-65535),末尾返回-1
int read(char[] cbuf) 读取字符到数组 返回实际读取的字符数,末尾返回-1
int read(char[] cbuf, int off, int len) 读取字符到数组的一部分 同上
long skip(long n) 跳过n个字符 返回实际跳过的字符数
boolean ready() 是否可读取 返回布尔值
void close() 关闭流 无
boolean markSupported() 是否支持mark 返回布尔值
void mark(int readAheadLimit) 标记当前位置 无
void reset() 重置到最后一次mark的位置 无
Writer核心方法
方法签名 描述 返回值说明
void write(int c) 写入一个字符 无
void write(char[] cbuf) 写入字符数组 无
void write(char[] cbuf, int off, int len) 写入字符数组的一部分 无
void write(String str) 写入字符串 无
void write(String str, int off, int len) 写入字符串的一部分 无
Writer append(char c) 追加一个字符 返回Writer本身
Writer append(CharSequence csq) 追加字符序列 返回Writer本身
Writer append(CharSequence csq, int start, int end) 追加字符序列的一部分 返回Writer本身
void flush() 刷新缓冲区 无
void close() 关闭流 无

三、IO流实战示例

3.1 文件读写基础示例

字节流文件复制
java 复制代码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopyExample {
    public static void main(String[] args) {
        // 定义源文件和目标文件路径
        String sourceFile = "source.jpg";
        String targetFile = "target.jpg";
        
        // 使用try-with-resources确保流自动关闭
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(targetFile)) {
            
            // 创建缓冲区(通常8KB是比较理想的缓冲区大小)
            byte[] buffer = new byte[8192];
            int bytesRead;
            
            // 读取源文件并写入目标文件
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
            
            System.out.println("文件复制完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
字符流文本文件读写
java 复制代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class TextFileExample {
    public static void main(String[] args) {
        String inputFile = "input.txt";
        String outputFile = "output.txt";
        
        try (BufferedReader reader = new BufferedReader(new FileReader(inputFile));
             BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {
            
            String line;
            int lineNumber = 1;
            
            // 逐行读取并处理
            while ((line = reader.readLine()) != null) {
                // 添加行号并写入新文件
                writer.write(lineNumber + ": " + line);
                writer.newLine(); // 换行
                lineNumber++;
            }
            
            System.out.println("文本处理完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.2 缓冲流性能对比

缓冲流可以显著提高IO性能,下面通过一个例子展示差异:

java 复制代码
import java.io.*;

public class BufferedStreamBenchmark {
    private static final String FILE_PATH = "large_file.dat";
    private static final int FILE_SIZE_MB = 100; // 100MB测试文件
    
    public static void main(String[] args) throws IOException {
        // 创建测试文件
        createTestFile(FILE_PATH, FILE_SIZE_MB);
        
        // 测试无缓冲读取
        long startTime = System.currentTimeMillis();
        readWithoutBuffer(FILE_PATH);
        long duration = System.currentTimeMillis() - startTime;
        System.out.println("无缓冲读取耗时: " + duration + "ms");
        
        // 测试缓冲读取
        startTime = System.currentTimeMillis();
        readWithBuffer(FILE_PATH);
        duration = System.currentTimeMillis() - startTime;
        System.out.println("缓冲读取耗时: " + duration + "ms");
        
        // 删除测试文件
        new File(FILE_PATH).delete();
    }
    
    private static void createTestFile(String path, int sizeMB) throws IOException {
        try (FileOutputStream fos = new FileOutputStream(path);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            
            byte[] data = new byte[1024]; // 1KB数据块
            for (int i = 0; i < 1024 * sizeMB; i++) { // 写入sizeMB MB数据
                bos.write(data);
            }
        }
    }
    
    private static void readWithoutBuffer(String path) throws IOException {
        try (FileInputStream fis = new FileInputStream(path)) {
            while (fis.read() != -1) { // 逐字节读取
                // 什么都不做,只读取
            }
        }
    }
    
    private static void readWithBuffer(String path) throws IOException {
        try (FileInputStream fis = new FileInputStream(path);
             BufferedInputStream bis = new BufferedInputStream(fis)) {
            
            while (bis.read() != -1) { // 使用缓冲流读取
                // 什么都不做,只读取
            }
        }
    }
}

典型输出结果:

复制代码
无缓冲读取耗时: 12345ms
缓冲读取耗时: 234ms

3.3 对象序列化与反序列化

Java对象序列化可以将对象转换为字节流,便于存储或传输。

java 复制代码
import java.io.*;
import java.util.Date;

public class SerializationExample {
    public static void main(String[] args) {
        // 要序列化的对象
        User user = new User("张三", "zhangsan@example.com", new Date(), 28);
        
        // 序列化到文件
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream("user.dat"))) {
            oos.writeObject(user);
            System.out.println("对象序列化完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 从文件反序列化
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream("user.dat"))) {
            User deserializedUser = (User) ois.readObject();
            System.out.println("反序列化得到的对象: " + deserializedUser);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

// 可序列化的User类
class User implements Serializable {
    private static final long serialVersionUID = 1L; // 序列化版本号
    
    private String name;
    private String email;
    private Date birthDate;
    private transient int age; // transient关键字标记的字段不会被序列化
    
    public User(String name, String email, Date birthDate, int age) {
        this.name = name;
        this.email = email;
        this.birthDate = birthDate;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", birthDate=" + birthDate +
                ", age=" + age +
                '}';
    }
}

注意事项:

  1. 类必须实现Serializable接口
  2. 使用transient关键字可以阻止字段被序列化
  3. 建议显式声明serialVersionUID以确保版本兼容性
  4. 序列化不保存静态变量状态

四、NIO深入解析

4.1 NIO核心组件

NIO有三个核心组件:Channel、Buffer和Selector。

Buffer详解

Buffer是NIO中的数据容器,主要实现类包括:

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

Buffer核心属性:

  • capacity: 缓冲区容量,创建时设定且不可改变
  • position: 当前读写位置
  • limit: 可读写的上限
  • mark: 标记位置,用于reset

Buffer常用方法:

方法 描述
allocate(int capacity) 分配新的缓冲区
put()/get() 写入/读取数据
flip() 切换为读模式,limit=position, position=0
clear() 清空缓冲区,position=0, limit=capacity
compact() 压缩缓冲区,保留未读数据
rewind() 重绕缓冲区,position=0
mark() 标记当前位置
reset() 重置到mark位置
Channel详解

Channel是NIO中的双向数据传输通道,主要实现包括:

  • FileChannel: 文件IO
  • SocketChannel: TCP网络IO
  • ServerSocketChannel: TCP服务端监听
  • DatagramChannel: UDP网络IO

Channel与Stream的区别:

  1. Channel是双向的,Stream是单向的
  2. Channel总是与Buffer交互
  3. Channel支持异步IO
Selector详解

Selector允许单线程处理多个Channel,实现多路复用IO。

核心方法:

  • open(): 创建Selector
  • select(): 阻塞直到有就绪的Channel
  • selectNow(): 非阻塞检查就绪Channel
  • selectedKeys(): 返回就绪的SelectionKey集合
  • wakeup(): 唤醒阻塞的select()

4.2 NIO实战示例

文件复制示例
java 复制代码
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class NIOFileCopy {
    public static void main(String[] args) {
        String sourceFile = "source.mp4";
        String targetFile = "target.mp4";
        
        try (RandomAccessFile source = new RandomAccessFile(sourceFile, "r");
             RandomAccessFile target = new RandomAccessFile(targetFile, "rw");
             FileChannel sourceChannel = source.getChannel();
             FileChannel targetChannel = target.getChannel()) {
            
            // 创建直接缓冲区(性能更好,但创建成本高)
            ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
            
            while (sourceChannel.read(buffer) != -1) {
                buffer.flip(); // 切换为读模式
                targetChannel.write(buffer);
                buffer.clear(); // 清空缓冲区,准备下一次读取
            }
            
            // 确保所有数据写入磁盘
            targetChannel.force(true);
            System.out.println("文件复制完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
非阻塞Socket示例
java 复制代码
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NonBlockingServer {
    public static void main(String[] args) throws IOException {
        // 创建Selector
        Selector selector = Selector.open();
        
        // 创建ServerSocketChannel并配置为非阻塞
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(8080));
        
        // 注册到Selector,监听ACCEPT事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务器启动,监听8080端口...");
        
        while (true) {
            // 阻塞直到有事件发生
            selector.select();
            
            // 获取就绪的SelectionKey集合
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
            
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                
                if (key.isAcceptable()) {
                    // 处理新连接
                    handleAccept(serverSocketChannel, selector);
                } else if (key.isReadable()) {
                    // 处理读事件
                    handleRead(key);
                }
                
                keyIterator.remove(); // 处理完后移除
            }
        }
    }
    
    private static void handleAccept(ServerSocketChannel serverChannel, 
                                    Selector selector) throws IOException {
        SocketChannel clientChannel = serverChannel.accept();
        clientChannel.configureBlocking(false);
        clientChannel.register(selector, SelectionKey.OP_READ);
        System.out.println("客户端连接: " + clientChannel.getRemoteAddress());
    }
    
    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        
        int bytesRead = channel.read(buffer);
        if (bytesRead == -1) {
            // 连接关闭
            channel.close();
            System.out.println("客户端断开连接");
            return;
        }
        
        buffer.flip();
        byte[] data = new byte[buffer.remaining()];
        buffer.get(data);
        String message = new String(data);
        System.out.println("收到消息: " + message);
        
        // 回显消息
        ByteBuffer response = ByteBuffer.wrap(("服务器回复: " + message).getBytes());
        channel.write(response);
    }
}

五、Java 8+中的IO/NIO增强

5.1 Files类新增方法

Java 8为java.nio.file.Files类添加了许多实用方法:

java 复制代码
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class FilesNewMethods {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get(".");
        
        // 1. 使用lines()方法逐行读取文件
        try (Stream<String> lines = Files.lines(Paths.get("data.txt"))) {
            lines.filter(line -> line.contains("error"))
                 .forEach(System.out::println);
        }
        
        // 2. 使用list()方法列出目录内容
        try (Stream<Path> paths = Files.list(path)) {
            paths.forEach(System.out::println);
        }
        
        // 3. 使用walk()方法递归遍历目录
        try (Stream<Path> paths = Files.walk(path, 3)) { // 最大深度3
            paths.filter(Files::isRegularFile)
                 .forEach(System.out::println);
        }
        
        // 4. 使用find()方法搜索文件
        try (Stream<Path> paths = Files.find(path, 3, 
                (p, attrs) -> attrs.isRegularFile() && p.toString().endsWith(".java"))) {
            paths.forEach(System.out::println);
        }
        
        // 5. 使用readAllBytes()和write()简化文件读写
        byte[] data = Files.readAllBytes(Paths.get("source.txt"));
        Files.write(Paths.get("target.txt"), data);
    }
}

5.2 BufferedReader新增lines()方法

java 复制代码
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.stream.Stream;

public class BufferedReaderLines {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
             Stream<String> lines = reader.lines()) {
            
            long count = lines.filter(line -> !line.isEmpty())
                              .count();
            System.out.println("非空行数: " + count);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5.3 Java 9的InputStream增强

Java 9为InputStream添加了实用的transferTo方法:

java 复制代码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class InputStreamTransfer {
    public static void main(String[] args) throws IOException {
        try (FileInputStream fis = new FileInputStream("source.txt");
             FileOutputStream fos = new FileOutputStream("target.txt")) {
            
            // Java 9新增方法,直接将输入流传输到输出流
            fis.transferTo(fos);
            System.out.println("文件传输完成!");
        }
    }
}

六、IO与NIO性能对比与选择

6.1 性能对比表格

场景 IO性能 NIO性能 推荐选择
大文件顺序读写 高 更高 NIO
小文件随机访问 中等 高 NIO
高并发网络服务(1000+) 低 高 NIO
低并发网络服务 中等 中等 均可
简单文本处理 高 中等 IO

6.2 选择建议

  1. 使用传统IO的场景:

    • 简单文件操作
    • 文本处理
    • 低并发网络应用
    • 需要简单易用的API
  2. 使用NIO的场景:

    • 高并发网络服务器
    • 需要非阻塞IO
    • 大文件处理
    • 需要内存映射文件
    • 需要更精细的IO控制
  3. 混合使用 :

    在实际开发中,可以结合两者的优势。例如:

    • 使用NIO处理网络连接
    • 使用传统IO处理业务逻辑
    • 使用NIO的文件通道进行大文件传输
    • 使用传统IO的API进行简单文件操作

七、高级主题与最佳实践

7.1 内存映射文件

内存映射文件(Memory-Mapped Files)是NIO提供的一种高效文件访问方式,它将文件直接映射到内存中:

java 复制代码
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MemoryMappedFileExample {
    public static void main(String[] args) throws Exception {
        // 文件路径和大小
        String filePath = "large_file.dat";
        long fileSize = 1024 * 1024 * 100; // 100MB
        
        try (RandomAccessFile file = new RandomAccessFile(filePath, "rw");
             FileChannel channel = file.getChannel()) {
            
            // 将文件映射到内存
            MappedByteBuffer buffer = channel.map(
                FileChannel.MapMode.READ_WRITE, // 读写模式
                0,                            // 起始位置
                fileSize                       // 映射区域大小
            );
            
            // 写入数据
            for (int i = 0; i < fileSize; i++) {
                buffer.put((byte) (i % 128));
            }
            
            // 读取数据
            buffer.flip();
            byte[] data = new byte[100];
            buffer.get(data, 0, data.length);
            
            System.out.println("前100字节数据: " + new String(data));
        }
    }
}

适用场景:

  • 超大文件随机访问
  • 进程间通信
  • 高频更新的文件

7.2 文件锁

NIO提供了文件锁机制,防止多个进程同时修改同一文件:

java 复制代码
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class FileLockExample {
    public static void main(String[] args) throws Exception {
        String filePath = "shared.txt";
        
        try (RandomAccessFile file = new RandomAccessFile(filePath, "rw");
             FileChannel channel = file.getChannel()) {
            
            // 获取排他锁
            FileLock lock = channel.lock();
            try {
                System.out.println("获得文件锁,开始操作文件...");
                // 执行文件操作
                Thread.sleep(5000); // 模拟长时间操作
            } finally {
                lock.release();
                System.out.println("释放文件锁");
            }
        }
    }
}

7.3 异步IO (AIO)

Java 7引入了AsynchronousFileChannel支持异步IO:

java 复制代码
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;

public class AsyncFileIOExample {
    public static void main(String[] args) {
        Path path = Paths.get("large_file.dat");
        
        try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(
                path, StandardOpenOption.READ)) {
            
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            long position = 0;
            
            // 异步读取
            Future<Integer> operation = channel.read(buffer, position);
            
            while (!operation.isDone()) {
                System.out.println("执行其他任务...");
                Thread.sleep(500);
            }
            
            int bytesRead = operation.get();
            buffer.flip();
            byte[] data = new byte[buffer.limit()];
            buffer.get(data);
            System.out.println("读取数据: " + new String(data));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

7.4 IO最佳实践

  1. 始终关闭资源 :

    使用try-with-resources确保资源被正确关闭

  2. 合理使用缓冲:

    • 对于文件IO,使用BufferedInputStream/BufferedOutputStream
    • 对于NIO,使用适当大小的Buffer
  3. 选择正确的流类型:

    • 文本数据使用字符流
    • 二进制数据使用字节流
  4. 处理大文件:

    • 使用NIO的FileChannel
    • 考虑内存映射文件
    • 分块处理,避免内存不足
  5. 异常处理:

    • 区分可恢复和不可恢复错误
    • 提供有意义的错误信息
    • 考虑重试机制
  6. 性能监控:

    • 监控IO操作耗时
    • 识别瓶颈并进行优化

八、常见问题与解决方案

8.1 文件编码问题

问题:读取文本文件时出现乱码

解决方案:

java 复制代码
// 指定正确的字符编码
try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(
            new FileInputStream("file.txt"), "UTF-8"))) {
    // 读取文件
}

8.2 文件锁定问题

问题:在Windows上无法删除或修改刚使用过的文件

解决方案:

java 复制代码
try (FileInputStream fis = new FileInputStream(file)) {
    // 使用文件
} // 自动关闭流,释放文件锁

// 或者强制释放资源
System.gc(); // 有时可以帮助释放未正确关闭的资源

8.3 内存不足问题

问题:读取大文件时出现OutOfMemoryError

解决方案:

  1. 使用流式处理,避免一次性加载整个文件
  2. 使用NIO的FileChannel和MappedByteBuffer
  3. 增加JVM堆内存:-Xmx参数

8.4 文件路径问题

问题:跨平台文件路径不一致

解决方案:

java 复制代码
// 使用Paths.get()或File.separator
Path path = Paths.get("data", "files", "example.txt");
// 或者
String path = "data" + File.separator + "files" + File.separator + "example.txt";

九、总结

Java IO和NIO提供了丰富的API来处理各种输入输出需求。传统IO简单易用,适合大多数常规场景;NIO则提供了更高的性能和灵活性,特别适合高并发和大数据量处理。从Java 7开始引入的NIO 2.0进一步增强了文件系统操作的能力。

关键点回顾:

  1. 理解流的概念和分类
  2. 掌握字节流和字符流的区别与使用场景
  3. 熟练使用缓冲流提高IO性能
  4. 了解NIO的核心组件:Channel、Buffer和Selector
  5. 掌握Java 8+对IO/NIO的增强功能
  6. 根据具体场景选择合适的IO方案

Java 的 IO 与 NIO 流就像数据快递员,IO 慢悠悠,NIO 风驰电掣,用错了,数据就像迷路的小孩啦!

点赞的明天瘦10斤,不点的...胖在我心里(对手指)。

相关推荐
泡茶喝茶写代码1 小时前
A股量化数据工程:从 REST 接口到策略信号(第 8 篇):成长能力因子:营收与利润增速
java·python·股票数据api·股票数据api接口·股票量化数据api·股票量化数据接口·股票数据api数据
汤姆yu1 小时前
Gemini 4 Argon模型综述:技术、能力与实际使用指南
网络·安全·web安全·ai·大模型
Seraphina362 小时前
SQL注入(二)盲注
网络·数据库·经验分享·笔记·sql
\光辉岁月/2 小时前
7.javase-面向对象
java·开发语言
weixin_531094692 小时前
heap_4内存管理
java·开发语言·算法
程序员南飞2 小时前
win系统安装minio
java·数据结构·算法
2401_868534783 小时前
无线网络规划设计
服务器·网络
螺蛳粉 螺蛳粉3 小时前
第二篇:keepalived VRRP 原理篇:协议与 VIP 漂移机制深入解析
网络·智能路由器·负载均衡·keepalived·高可用
Escalating_xu3 小时前
【Python】使用库:标准库、第三方库、pip、项目实战与程序打包
java·python·pip
盟接之桥3 小时前
AI助手:你的7×24小时智能管家——让异常预警无处不在
大数据·网络·数据库·人工智能·制造·ai编程