JDK-In-Action-NIO-FileChannel
FileChannel
文件管道
- 支持随机读写
- 支持文件截断
- 支持文件写强制刷新到磁盘
- 支持独占或共享的文件锁
- 支持直接内存访问(DMA)的大文件传输
map
- 支持文件到其他channel的缓冲区传输优化
transferFrom
和transferTo
API Example
File Channel截断 Truncate
从FileChannel写数据();
final File file = new File("E:/tmp/tmp.txt");
final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
//截断,注意会修改 position 的值为 5
channel.position(6);//6>5
channel.truncate(5);
//position
assertEquals(channel.position(), 5L);
//获取文件大小
assertEquals(channel.size(), 5L);
从 File Channel写数据
final File file = new File("E:/tmp/tmp.txt");
final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
final ByteBuffer buffer = ByteBuffer.wrap("ABCDEFG".getBytes());
//由于write不保证一次完全写入,因此需要使用循环,填充channel知道缓冲区为空
while (buffer.remaining() > 0) {
//实际写入字节数
int write = channel.write(buffer);
}
assertEquals(channel.position(), 7L);
//从指定位置开始读写
channel.position(3);
buffer.flip();
while (buffer.remaining() > 0) {
//实际写入字节数
int write = channel.write(buffer);
}
channel.close();
从 File Channel读数据
从FileChannel写数据();
final File file = new File("E:/tmp/tmp.txt");
final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.READ);
//获取文件大小
assertEquals(channel.size(), 10L);
final ByteBuffer buffer = ByteBuffer.allocate(1024);
int r = -1;
while ((r = channel.read(buffer)) >= 0) {
System.out.println(new String(buffer.array(), 0, r));
buffer.clear();
}
//从指定位置开始读写
channel.position(3);
while ((r = channel.read(buffer)) >= 0) {
System.out.println(new String(buffer.array(), 0, r));
buffer.clear();
}
channel.close();
ABCABCDEFG
ABCDEFG
创建 File Channel之 Open
final File file = new File("E:/tmp/tmp.txt");
final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.READ);
assertEquals(channel.position(), 0L);
channel.close();
创建 File Channel之 Random Access File
final File file = new File("E:/tmp/tmp.txt");
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
randomAccessFile.writeInt(9);
assertEquals(randomAccessFile.getFilePointer(), 4L);
FileChannel channel = randomAccessFile.getChannel();
//注意,channel会继承文件指针位置
assertEquals(channel.position(), 4L);
channel.close();
强制刷新 Force
final File file = new File("E:/tmp/tmp.txt");
final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
final ByteBuffer buffer = ByteBuffer.wrap("ABCDEFG".getBytes());
//由于write不保证一次完全写入,因此需要使用循环,填充channel知道缓冲区为空
while (buffer.remaining() > 0) {
//实际写入字节数
int write = channel.write(buffer);
}
assertEquals(channel.position(), 7L);
//强制刷新写入的数据到磁盘,并且同步元素数据(例如权限等)
channel.force(true);
文件锁 Lock
final File file = new File("E:/tmp/tmp.txt");
final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
FileLock lock = null;
try {
//文件独占锁,还支持指定范围的共享锁
lock = channel.lock();
} finally {
if (lock != null) {
lock.release();
}
}
直接内存访问映射map
final File file = new File("E:/tmp/tmp.txt");
final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE);
//映射一个可以读写的缓存区
final MappedByteBuffer mapBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
assertEquals(mapBuffer.position(), 0);
mapBuffer.put("DMA".getBytes());
mapBuffer.force();
channel.close();
System.out.println(new String(Files.readAllBytes(file.toPath())));
DMADEFGEFG
引用
- 源码下载
java.nio.channels.FileChannel
Source Code