欢迎光临
我们一直在努力

DeepSeek Java NIO Channels 演示

Java NIO Channels 演示

NIO Channels 是 Java NIO 的核心组件之一,提供了比传统 I/O 更高效的数据传输方式。下面是一个完整的演示:

1. 基本通道类型演示

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;

public class NIOChannelsDemo {

public static void main(String[] args) {
System.out.println("=== Java NIO Channels 演示 ===\\n");

try {
// 1. 文件通道演示
fileChannelDemo();

// 2. 缓冲区演示
bufferDemo();

// 3. 文件复制对比
fileCopyComparison();

// 4. Socket通道演示(简单示例)
socketChannelDemo();

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 文件通道操作演示
*/

private static void fileChannelDemo() throws IOException {
System.out.println("1. 文件通道操作演示");
System.out.println("-".repeat(50));

// 创建测试文件
Path testFile = Paths.get("test_data.txt");
String content = "Java NIO Channels 演示\\n" +
"第二行数据\\n" +
"第三行数据\\n" +
"第四行数据\\n";

// 写入文件 – 使用 FileChannel
System.out.println("写入文件内容:");
System.out.println(content);

try (FileChannel writeChannel = FileChannel.open(testFile,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING)) {

ByteBuffer buffer = ByteBuffer.wrap(content.getBytes());
writeChannel.write(buffer);
System.out.println("文件写入完成");
}

// 读取文件 – 使用 FileChannel
System.out.println("\\n读取文件内容:");
try (FileChannel readChannel = FileChannel.open(testFile, StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = readChannel.read(buffer);

buffer.flip(); // 切换为读模式
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println("读取字节数: " + bytesRead);
}

// 文件位置操作
System.out.println("\\n文件位置操作:");
try (RandomAccessFile raf = new RandomAccessFile(testFile.toFile(), "r");
FileChannel channel = raf.getChannel()) {

System.out.println("文件大小: " + channel.size() + " 字节");

// 定位到第10个字节
channel.position(10);
ByteBuffer buffer = ByteBuffer.allocate(20);
channel.read(buffer);
buffer.flip();

System.out.print("从位置10读取的内容: ");
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println();
}

// 清理测试文件
Files.deleteIfExists(testFile);
System.out.println();
}

/**
* 缓冲区操作演示
*/

private static void bufferDemo() {
System.out.println("2. 缓冲区操作演示");
System.out.println("-".repeat(50));

// 创建ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(50);
printBufferState("初始状态", buffer);

// 写入数据
String data = "Hello NIO!";
buffer.put(data.getBytes());
printBufferState("写入数据后", buffer);

// 切换到读模式
buffer.flip();
printBufferState("调用flip()后", buffer);

// 读取数据
System.out.print("读取的数据: ");
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println();
printBufferState("读取数据后", buffer);

// 清空缓冲区
buffer.clear();
printBufferState("调用clear()后", buffer);

// 使用 wrap 创建缓冲区
ByteBuffer wrappedBuffer = ByteBuffer.wrap("包装的数据".getBytes());
printBufferState("包装缓冲区", wrappedBuffer);

// mark 和 reset 操作
ByteBuffer markBuffer = ByteBuffer.allocate(20);
markBuffer.put("标记测试".getBytes());
markBuffer.flip();

markBuffer.get(); // 读取一个字节
markBuffer.mark(); // 设置标记

System.out.print("\\n标记后读取: ");
while (markBuffer.hasRemaining()) {
System.out.print((char) markBuffer.get());
}

markBuffer.reset(); // 重置到标记位置
System.out.print("\\n重置后读取: ");
while (markBuffer.hasRemaining()) {
System.out.print((char) markBuffer.get());
}
System.out.println("\\n");
}

/**
* 文件复制性能对比
*/

private static void fileCopyComparison() throws IOException {
System.out.println("3. 文件复制性能对比");
System.out.println("-".repeat(50));

// 创建测试文件
Path sourceFile = Paths.get("source_large.txt");
Path dest1 = Paths.get("dest_traditional.txt");
Path dest2 = Paths.get("dest_nio.txt");

// 生成大文件内容
StringBuilder content = new StringBuilder();
for (int i = 0; i < 10000; i++) {
content.append("这是第 ").append(i).append(" 行数据。".repeat(10)).append("\\n");
}

Files.write(sourceFile, content.toString().getBytes());
System.out.println("创建测试文件大小: " + Files.size(sourceFile) + " 字节");

// 传统IO复制
long startTime = System.nanoTime();
try (InputStream in = new FileInputStream(sourceFile.toFile());
OutputStream out = new FileOutputStream(dest1.toFile())) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) != –1) {
out.write(buffer, 0, bytesRead);
}
}
long traditionalTime = System.nanoTime() – startTime;

// NIO复制
startTime = System.nanoTime();
try (FileChannel sourceChannel = FileChannel.open(sourceFile, StandardOpenOption.READ);
FileChannel destChannel = FileChannel.open(dest2,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING)) {

// 方法1: 使用transferTo (零拷贝)
sourceChannel.transferTo(0, sourceChannel.size(), destChannel);

// 方法2: 也可以使用transferFrom
// destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
}
long nioTime = System.nanoTime() – startTime;

System.out.println("传统IO复制时间: " + (traditionalTime / 1_000_000.0) + " ms");
System.out.println("NIO复制时间: " + (nioTime / 1_000_000.0) + " ms");
System.out.println("性能提升: " +
String.format("%.2f", (traditionalTime – nioTime) * 100.0 / traditionalTime) + "%");

// 验证文件相同
long sourceSize = Files.size(sourceFile);
long dest1Size = Files.size(dest1);
long dest2Size = Files.size(dest2);

System.out.println("\\n文件大小验证:");
System.out.println("源文件: " + sourceSize + " 字节");
System.out.println("传统IO复制: " + dest1Size + " 字节 " +
(sourceSize == dest1Size ? "✓" : "✗"));
System.out.println("NIO复制: " + dest2Size + " 字节 " +
(sourceSize == dest2Size ? "✓" : "✗"));

// 清理文件
Files.deleteIfExists(sourceFile);
Files.deleteIfExists(dest1);
Files.deleteIfExists(dest2);
System.out.println();
}

/**
* Socket通道简单演示
*/

private static void socketChannelDemo() throws IOException {
System.out.println("4. Socket通道演示");
System.out.println("-".repeat(50));

// 注意:实际应用中需要启动服务器和客户端
System.out.println("SocketChannel 使用示例:");
System.out.println("""
// 客户端代码示例
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost", 8080));

// 设置为非阻塞模式
socketChannel.configureBlocking(false);

// 写入数据
ByteBuffer buffer = ByteBuffer.wrap("Hello Server".getBytes());
while (buffer.hasRemaining()) {
socketChannel.write(buffer);
}

// 服务器端代码示例
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);

while (true) {
SocketChannel clientChannel = serverSocketChannel.accept();
if (clientChannel != null) {
// 处理客户端连接
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
clientChannel.read(readBuffer);
// … 处理数据
}
}
""");

System.out.println("注意:这是一个代码示例,实际运行需要完整的服务器/客户端实现");
}

/**
* 打印缓冲区状态
*/

private static void printBufferState(String title, ByteBuffer buffer) {
System.out.printf("%-20s: capacity=%d, position=%d, limit=%d, remaining=%d\\n",
title,
buffer.capacity(),
buffer.position(),
buffer.limit(),
buffer.remaining());
}
}

2. 高级通道特性演示

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;

public class AdvancedChannelFeatures {

/**
* 通道间的数据传输(零拷贝)
*/

public static void transferBetweenChannels() throws IOException {
System.out.println("\\n=== 通道间数据传输(零拷贝)===");

// 创建两个测试文件
Path source = Paths.get("source_transfer.txt");
Path dest = Paths.get("dest_transfer.txt");

Files.write(source, "这是通过transferTo传输的数据".getBytes());

try (FileChannel sourceChannel = FileChannel.open(source, StandardOpenOption.READ);
FileChannel destChannel = FileChannel.open(dest,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE)) {

// 使用transferTo – 更高效的文件复制
long transferred = sourceChannel.transferTo(0, sourceChannel.size(), destChannel);
System.out.println("传输的字节数: " + transferred);
}

// 读取验证
System.out.println("目标文件内容: " + new String(Files.readAllBytes(dest)));

Files.deleteIfExists(source);
Files.deleteIfExists(dest);
}

/**
* 内存映射文件演示
*/

public static void memoryMappedFileDemo() throws IOException {
System.out.println("\\n=== 内存映射文件演示 ===");

Path mappedFile = Paths.get("mapped_file.txt");
String content = "内存映射文件内容\\n第二行\\n第三行";

// 写入文件
Files.write(mappedFile, content.getBytes());

try (FileChannel channel = FileChannel.open(mappedFile,
StandardOpenOption.READ,
StandardOpenOption.WRITE)) {

// 创建内存映射
MappedByteBuffer mappedBuffer = channel.map(
FileChannel.MapMode.READ_WRITE, 0, channel.size());

System.out.println("映射缓冲区大小: " + mappedBuffer.capacity());

// 读取内容
System.out.print("映射文件内容: ");
while (mappedBuffer.hasRemaining()) {
System.out.print((char) mappedBuffer.get());
}
System.out.println();

// 修改内容(直接在内存中修改)
mappedBuffer.position(0); // 重置位置
mappedBuffer.put("修改后的".getBytes());

// 强制同步到磁盘
mappedBuffer.force();
System.out.println("修改已同步到磁盘");
}

// 验证修改
System.out.println("文件实际内容: " + new String(Files.readAllBytes(mappedFile)));

Files.deleteIfExists(mappedFile);
}

/**
* 分散和聚集IO演示
*/

public static void scatterGatherDemo() throws IOException {
System.out.println("\\n=== 分散和聚集IO演示 ===");

Path scatterFile = Paths.get("scatter_gather.txt");

try (FileChannel channel = FileChannel.open(scatterFile,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.READ)) {

// 聚集写入:将多个缓冲区的内容写入一个通道
ByteBuffer header = ByteBuffer.wrap("Header: ".getBytes());
ByteBuffer body = ByteBuffer.wrap("Body Content".getBytes());
ByteBuffer footer = ByteBuffer.wrap("\\nFooter".getBytes());

ByteBuffer[] buffers = {header, body, footer};

// 写入前需要确保所有缓冲区都在正确位置
for (ByteBuffer buf : buffers) {
buf.rewind();
}

channel.write(buffers);
System.out.println("聚集写入完成");

// 分散读取:从一个通道读取数据到多个缓冲区
channel.position(0); // 重置文件位置

ByteBuffer readHeader = ByteBuffer.allocate(8);
ByteBuffer readBody = ByteBuffer.allocate(12);
ByteBuffer readFooter = ByteBuffer.allocate(7);

ByteBuffer[] readBuffers = {readHeader, readBody, readFooter};

long bytesRead = channel.read(readBuffers);
System.out.println("读取字节数: " + bytesRead);

// 打印读取的内容
System.out.print("分散读取内容: ");
for (ByteBuffer buf : readBuffers) {
buf.flip();
while (buf.hasRemaining()) {
System.out.print((char) buf.get());
}
}
System.out.println();
}

Files.deleteIfExists(scatterFile);
}

/**
* 文件锁定演示
*/

public static void fileLockingDemo() throws IOException {
System.out.println("\\n=== 文件锁定演示 ===");

Path lockFile = Paths.get("lock_test.txt");
Files.write(lockFile, "测试文件锁定".getBytes());

try (FileChannel channel = FileChannel.open(lockFile,
StandardOpenOption.READ,
StandardOpenOption.WRITE)) {

// 获取独占锁
FileLock lock = channel.lock();
System.out.println("获取文件锁: " +
(lock.isShared() ? "共享锁" : "独占锁"));
System.out.println("锁的位置: " + lock.position() +
", 大小: " + lock.size());

// 在持有锁的情况下操作文件
ByteBuffer buffer = ByteBuffer.wrap("\\n在锁保护下写入".getBytes());
channel.position(channel.size());
channel.write(buffer);

// 释放锁
lock.release();
System.out.println("文件锁已释放");
}

System.out.println("最终文件内容: " + new String(Files.readAllBytes(lockFile)));
Files.deleteIfExists(lockFile);
}

public static void main(String[] args) throws IOException {
System.out.println("=== Java NIO 高级特性演示 ===\\n");

transferBetweenChannels();
memoryMappedFileDemo();
scatterGatherDemo();
fileLockingDemo();
}
}

3. 使用示例和最佳实践

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.util.*;

/**
* 实用的NIO工具类示例
*/

public class NIOUtils {

/**
* 高效的文本文件读取
*/

public static List<String> readLines(Path filePath) throws IOException {
List<String> lines = new ArrayList<>();

try (FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocateDirect(8192); // 使用直接缓冲区
StringBuilder lineBuilder = new StringBuilder();
byte[] lineSeparator = System.lineSeparator().getBytes();

while (channel.read(buffer) != –1) {
buffer.flip();

while (buffer.hasRemaining()) {
char c = (char) buffer.get();
if (c == '\\n') {
lines.add(lineBuilder.toString());
lineBuilder.setLength(0);
} else if (c != '\\r') {
lineBuilder.append(c);
}
}

buffer.compact();
}

if (lineBuilder.length() > 0) {
lines.add(lineBuilder.toString());
}
}

return lines;
}

/**
* 高效的大文件复制
*/

public static void copyLargeFile(Path source, Path destination) throws IOException {
try (FileChannel sourceChannel = FileChannel.open(source, StandardOpenOption.READ);
FileChannel destChannel = FileChannel.open(destination,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING)) {

long position = 0;
long size = sourceChannel.size();

// 分块传输,适合超大文件
while (position < size) {
position += sourceChannel.transferTo(position, 64 * 1024 * 1024, destChannel);
}
}
}

/**
* 使用内存映射快速搜索文件
*/

public static long searchInFile(Path filePath, String searchText) throws IOException {
try (FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ)) {
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_ONLY, 0, channel.size());

byte[] searchBytes = searchText.getBytes();
long count = 0;

for (int i = 0; i <= buffer.limit() – searchBytes.length; i++) {
boolean match = true;
for (int j = 0; j < searchBytes.length; j++) {
if (buffer.get(i + j) != searchBytes[j]) {
match = false;
break;
}
}
if (match) {
count++;
}
}

return count;
}
}

/**
* 非阻塞文件监控(简单示例)
*/

public static void watchFileChanges(Path directory) throws IOException {
WatchService watchService = FileSystems.getDefault().newWatchService();

directory.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE);

System.out.println("开始监控目录: " + directory);

Thread watchThread = new Thread(() -> {
try {
while (true) {
WatchKey key = watchService.take();

for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();

if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}

@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();

System.out.printf("事件: %s, 文件: %s\\n", kind.name(), fileName);
}

if (!key.reset()) {
break;
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

watchThread.setDaemon(true);
watchThread.start();
}
}

总结

NIO Channels 的主要优势:

  • 更高的性能:使用缓冲区和通道减少系统调用
  • 零拷贝技术:transferTo() 和 transferFrom() 方法
  • 内存映射文件:通过 MappedByteBuffer 直接操作文件
  • 非阻塞IO:支持异步操作
  • 分散/聚集:高效处理多个缓冲区
  • 使用建议:

    • 处理大文件时使用内存映射
    • 文件复制使用 transferTo()/transferFrom()
    • 需要高性能时使用直接缓冲区
    • 注意正确处理缓冲区的 flip/clear/rewind 操作

    这个演示涵盖了 NIO Channels 的核心概念和实用技巧,可以根据具体需求选择合适的方法。

    赞(0)
    未经允许不得转载:171主机测评 » DeepSeek Java NIO Channels 演示
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址