Java NIO详解
什么是NIO
Java NIO(New IO)是JDK 1.4引入的非阻塞IO框架,提供了与标准IO不同的工作方式。NIO支持面向缓冲区的、基于通道的IO操作。
Buffer(缓冲区)
Buffer是数据容器,用于存储和操作数据。
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
public class BufferDemo {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
System.out.println("容量: " + buffer.capacity());
System.out.println("限制: " + buffer.limit());
System.out.println("位置: " + buffer.position());
buffer.put((byte) 'H');
buffer.put((byte) 'e');
buffer.put((byte) 'l');
System.out.println("写入后位置: " + buffer.position());
buffer.flip();
System.out.println("flip后位置: " + buffer.position());
System.out.println("flip后限制: " + buffer.limit());
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println();
buffer.clear();
System.out.println("clear后位置: " + buffer.position());
}
}
Buffer类型
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.IntBuffer;
public class BufferTypesDemo {
public static void main(String[] args) {
IntBuffer intBuffer = IntBuffer.allocate(10);
intBuffer.put(10);
intBuffer.put(20);
intBuffer.put(30);
intBuffer.flip();
while (intBuffer.hasRemaining()) {
System.out.print(intBuffer.get() + " ");
}
System.out.println();
CharBuffer charBuffer = CharBuffer.wrap("Hello NIO");
char[] chars = new char[5];
charBuffer.get(chars, 0, 5);
System.out.println(new String(chars));
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
System.out.println("Direct Buffer: " + byteBuffer.isDirect());
}
}
Channel(通道)
Channel是NIO中用于IO操作的连接点。
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ChannelDemo {
public static void main(String[] args) {
String source = "source.txt";
String target = "target.txt";
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
System.out.println("文件复制完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Scatter/Gather操作
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ScatterGatherDemo {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("scatter.txt");
FileChannel channel = fos.getChannel()) {
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
header.put("Header Content".getBytes());
header.flip();
body.put("Body Content".getBytes());
body.flip();
ByteBuffer[] buffers = {header, body};
channel.write(buffers);
System.out.println("Scatter写入完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件通道复制
import java.io.*;
import java.nio.channels.FileChannel;
public class FileChannelCopyDemo {
public static void main(String[] args) {
String source = "large_file.dat";
String target = "copy_file.dat";
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
long size = inChannel.size();
long transferred = 0;
while (transferred < size) {
transferred += inChannel.transferTo(transferred, size - transferred, outChannel);
}
System.out.println("文件复制完成,大小: " + size + " bytes");
} catch (IOException e) {
e.printStackTrace();
}
}
}
内存映射文件
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class MemoryMappedFileDemo {
public static void main(String[] args) {
String fileName = "mapped.txt";
try (RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileChannel channel = raf.getChannel()) {
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_WRITE, 0, 1024);
buffer.put("Hello Memory Mapped File".getBytes());
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
System.out.println("读取内容: " + new String(data));
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO文件操作
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.stream.Stream;
public class NIOFileDemo {
public static void main(String[] args) {
Path path = Paths.get("test_dir");
try {
Files.createDirectories(path);
System.out.println("目录创建成功");
} catch (IOException e) {
e.printStackTrace();
}
try {
Files.createFile(path.resolve("file1.txt"));
Files.createFile(path.resolve("file2.txt"));
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
try (Stream<Path> stream = Files.list(path)) {
stream.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
try {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println("文件: " + file);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO vs IO
- 面向流 vs 面向缓冲:IO面向流,NIO面向缓冲区
- 阻塞 vs 非阻塞:IO是阻塞的,NIO支持非阻塞
- 选择器:NIO支持Selector实现多路复用
总结
Java NIO提供了更高效、更灵活的IO操作方式。理解Buffer、Channel和内存映射的概念,能帮助你构建高性能的IO密集型应用。