Java NIO:FileChannel

一、FileChannel的优势

  FileChannel 的优点包括:

  • 在文件的特定位置读取和写入
  • 将文件的一部分直接加载到内存中,这样效率最高;
  • 可以以更快的速度将文件数据从一个通道传输到另一个通道
  • 可以锁定文件的一部分以限制其他线程访问;
  • 为了避免数据丢失,我们可以强制将更新的文件立即写入存储

 

二、使用FileChannel打开文件

 1. 使用 RandomAccessFile 打开 FileChannel :

1 RandomAccessFile reader = new RandomAccessFile(file, "r");
2 FileChannel channel = reader.getChannel();

关闭 RandomAccessFile 也会关闭关联的通道。

 模式“r”表示通道仅开发“读取”,模式“rw”是开放“读取”和“写入”。此外还有:

“rw”—— 对文件的内容的每次更新,并且在你关闭文件之前不会更改修改日期。

“rws”—— 对文件的内容和文件的修改日期(元数据)的每一次更新都同步写入到底层存储设备中;

“rwd”—— 对文件的内容的每一次更新都同步写入底层存储器中,但在文件关闭之前修改日期(元数据)可能不会更改。

 模式“rwd” 的写入速度比“rw” 慢得多,而 “rws” 又更慢得多。使用“rwd”可用于减少执行的I/O操作的数量,使用“rws”需要更新文件内容及其要写入的元数据,这起码要进行一次低级I/O操作。

 PS:文件还可能有一些相关的元数据,例如访问权限、内容类型和上次修改时间。

 

 2. 使用 FileInputStream 打开 FileChannel :

1 FileInputStream fin= new FileInputStream(file);
2 FileChannel channel = fin.getChannel();

关闭 FileInputStream 也会关闭与其关联的通道。

 

三、从FileChannel读取数据

1 ByteBuffer buff = ByteBuffer.allocate(1024);
2 int noOfBytesRead = channel.read(buff);
3 String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8);

 分配一个Buffer,从FileChannel中读取数据到这个Buffer中。

 

四、使用FileChannel写入文件

1. 使用 RandomAccessFile 打开 FileChannel ,模式为“rw”,使用 ByteBuffer 来存储数据并写入文件。 

1 RandomAccessFile writer = new RandomAccessFile(file, "rw");
2 FileChannel channel = writer.getChannel();
3 ByteBuffer buff = ByteBuffer.wrap("Writing...".getBytes(StandardCharsets.UTF_8));
4 channel.write(buff);

2. 使用 FileOutputStream 打开 FileChannel 。

1 FileOutputStream fout = new FileOutputStream(file);
2 FileChannel channel = fout.getChannel();

 

五、获取位置

 在 FileChannel 的某个特定位置进行数据的读 / 写操作。可以通过调用 position() 方法获取 FileChannel 的当前位置。

1 long originalPosition = channel.position();
2 System.out.println(originalPosition);
3 channel.position(6);
4 long currentPosition = channel.position();
5 System.out.println(currentPosition);

 

六、获取文件大小

 FileChannel.size() 方法将返回该实例所关联文件的大小,单位是字节。

1 RandomAccessFile reader = new RandomAccessFile(file, "r");
2 FileChannel channel = reader.getChannel();
3 System.out.println(channel.size());
4 channel.close();
5 reader.close();

 

七、截断文件

 使用 FileChannel.truncate 方法将文件截断为给定的字节大小(截取前 n 个字节)。

 1 String input = "this is a test input";
 2 FileOutputStream fos = new FileOutputStream("src/main/resources/FILE.txt");
 3 FileChannel channel = fos.getChannel();
 4 
 5 ByteBuffer buffer = ByteBuffer.wrap(input.getBytes());
 6 channel.write(buffer);
 7 buffer.flip();
 8 
 9 channel.truncate(5);
10 System.out.println(channel.size());
11 
12 fos.close();
13 channel.close();

 

八、强制文件更新到底层存储

 操作系统可能出于性能原因缓存文件更改,如果系统崩溃,数据可能会丢失。要强制文件内容和元数据连续写入磁盘,我们可以使用 force 方法:

1 channel.force(true);

 出于性能方面的考虑,操作系统会将数据缓存在内存中,所以无法保证写入到 FileChannel 里的数据一定会即时写到磁盘上。

 

posted @ 2021-12-13 22:18  賣贾笔的小男孩  阅读(552)  评论(0编辑  收藏  举报