JDK-In-Action-NIO-FileChannel

FileChannel

文件管道

  • 支持随机读写
  • 支持文件截断
  • 支持文件写强制刷新到磁盘
  • 支持独占或共享的文件锁
  • 支持直接内存访问(DMA)的大文件传输map
  • 支持文件到其他channel的缓冲区传输优化transferFromtransferTo

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

引用

posted @ 2020-05-05 22:16  onion94  阅读(164)  评论(0编辑  收藏  举报