关键点说明
-  
文件打开选项:
-  
StandardOpenOption.CREATE- 文件不存在时创建 -  
StandardOpenOption.READ/WRITE- 读写权限 -  
StandardOpenOption.APPEND- 追加模式 -  
StandardOpenOption.TRUNCATE_EXISTING- 清空已存在文件 
 -  
 -  
缓冲区操作:
-  
ByteBuffer.wrap()包装现有字节数组 -  
buffer.flip()切换读写模式 -  
直接操作缓冲区提高性能
 
 -  
 -  
高效文件复制:
-  
transferTo()/transferFrom()方法比传统流复制更高效 
 -  
 -  
资源管理:
-  
使用try-with-resources确保通道自动关闭
 -  
文件锁需要显式释放
 
 -  
 
这些示例展示了FileChannel的基本读写操作、文件锁的使用以及内存映射文件的高效操作,可以根据实际需求进行调整和扩展。
1. 基本文件读写示例
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;public class FileChannelDemo {public static void main(String[] args) {String filePath = "test.txt";// 写入文件writeToFile(filePath, "Hello, FileChannel!");// 读取文件String content = readFromFile(filePath);System.out.println("文件内容: " + content);// 追加内容appendToFile(filePath, "\n这是追加的内容");// 再次读取System.out.println("追加后的内容: " + readFromFile(filePath));// 文件复制copyFile(filePath, "test_copy.txt");System.out.println("复制文件内容: " + readFromFile("test_copy.txt"));}// 写入文件(覆盖)public static void writeToFile(String filePath, String content) {try (FileChannel channel = FileChannel.open(Paths.get(filePath),StandardOpenOption.CREATE,StandardOpenOption.WRITE,StandardOpenOption.TRUNCATE_EXISTING)) {ByteBuffer buffer = ByteBuffer.wrap(content.getBytes());channel.write(buffer);System.out.println("写入文件成功");} catch (IOException e) {e.printStackTrace();}}// 读取文件public static String readFromFile(String filePath) {try (FileChannel channel = FileChannel.open(Paths.get(filePath),StandardOpenOption.READ)) {ByteBuffer buffer = ByteBuffer.allocate((int) channel.size());channel.read(buffer);buffer.flip();return new String(buffer.array(), 0, buffer.limit());} catch (IOException e) {e.printStackTrace();return null;}}// 追加内容到文件public static void appendToFile(String filePath, String content) {try (FileChannel channel = FileChannel.open(Paths.get(filePath),StandardOpenOption.WRITE,StandardOpenOption.APPEND)) {ByteBuffer buffer = ByteBuffer.wrap(content.getBytes());channel.write(buffer);System.out.println("追加内容成功");} catch (IOException e) {e.printStackTrace();}}// 文件复制public static void copyFile(String sourcePath, String targetPath) {try (FileChannel source = FileChannel.open(Paths.get(sourcePath),StandardOpenOption.READ);FileChannel target = FileChannel.open(Paths.get(targetPath),StandardOpenOption.CREATE,StandardOpenOption.WRITE,StandardOpenOption.TRUNCATE_EXISTING)) {// 使用transferTo进行高效的文件复制source.transferTo(0, source.size(), target);System.out.println("文件复制成功");} catch (IOException e) {e.printStackTrace();}}
} 
 
2. 使用文件锁的读写示例
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;public class FileChannelWithLockDemo {public static void main(String[] args) {String filePath = "locked_file.txt";// 线程1 - 写入数据new Thread(() -> {writeWithLock(filePath, "线程1写入的数据");}).start();// 线程2 - 尝试写入new Thread(() -> {writeWithLock(filePath, "线程2写入的数据");}).start();}public static void writeWithLock(String filePath, String content) {try (FileChannel channel = FileChannel.open(Paths.get(filePath),StandardOpenOption.CREATE,StandardOpenOption.WRITE,StandardOpenOption.APPEND)) {// 尝试获取排他锁System.out.println(Thread.currentThread().getName() + " 尝试获取文件锁...");FileLock lock = channel.lock();try {System.out.println(Thread.currentThread().getName() + " 获取到文件锁");// 模拟耗时操作Thread.sleep(2000);// 写入数据ByteBuffer buffer = ByteBuffer.wrap((content + "\n").getBytes());channel.write(buffer);System.out.println(Thread.currentThread().getName() + " 写入完成");} finally {lock.release();System.out.println(Thread.currentThread().getName() + " 释放文件锁");}} catch (IOException | InterruptedException e) {e.printStackTrace();}}
} 
3.内存映射文件示例
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;public class MemoryMappedFileDemo {public static void main(String[] args) {String filePath = "mapped_file.txt";// 写入内存映射文件writeMappedFile(filePath, "这是内存映射文件的内容");// 读取内存映射文件readMappedFile(filePath);}public static void writeMappedFile(String filePath, String content) {try (FileChannel channel = FileChannel.open(Paths.get(filePath),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE)) {// 创建内存映射MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, content.getBytes().length);// 直接操作内存buffer.put(content.getBytes());System.out.println("内存映射文件写入完成");} catch (IOException e) {e.printStackTrace();}}public static void readMappedFile(String filePath) {try (FileChannel channel = FileChannel.open(Paths.get(filePath),StandardOpenOption.READ)) {MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());byte[] bytes = new byte[(int) channel.size()];buffer.get(bytes);System.out.println("读取到的内容: " + new String(bytes));} catch (IOException e) {e.printStackTrace();}}
} 
FileChannel的lock详解
一、文件锁的基本概念
文件锁分为两种类型:
-  
排他锁(独占锁):
-  
同一时间只能有一个进程持有
 -  
其他进程无法获取任何类型的锁
 
 -  
 -  
共享锁(读锁):
-  
可以被多个进程同时持有
 -  
但只要有进程持有共享锁,就不能获取排他锁
 
 -  
 
二、lock()方法的使用
1. 基本锁定方式
FileChannel channel = FileChannel.open(Paths.get("test.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE);// 获取排他锁(默认)
FileLock exclusiveLock = channel.lock();// 获取共享锁(第三个参数为true)
FileLock sharedLock = channel.lock(0, Long.MAX_VALUE, true); 
2. 方法参数说明
public final FileLock lock(long position, long size, boolean shared) 
-  
position:锁定区域的起始位置 -  
size:锁定区域的大小(比特) -  
shared:是否为共享锁(true=共享锁,false=排他锁) 
3.非阻塞尝试锁定
FileLock tryLock = channel.tryLock(); // 非阻塞版本
if (tryLock == null) {// 获取锁失败
}
tryLock.release() 
四、注意事项
-  
锁的有效性:
-  
文件锁是建议性的(advisory),不是强制性的
 -  
只有遵守锁协议的进程才会受锁影响
 -  
操作系统可能有不同的实现方式
 
 -  
 -  
性能考虑:
-  
频繁获取/释放锁会影响性能
 -  
锁定大文件区域可能降低并发性
 
 -  
 -  
异常处理:
-  
OverlappingFileLockException:当请求的锁区域与现有锁重叠时抛出 -  
NonWritableChannelException:尝试在只读通道上获取排他锁 
 -  
 -  
平台差异:
-  
Windows系统上的实现与Unix-like系统不同
 -  
某些网络文件系统可能不支持文件锁
 
 -  
 
五、适用场景
-  
多进程共享文件访问控制
 -  
防止文件被多个写入者同时修改
 -  
实现简单的进程间同步机制
 -  
保护关键配置文件不被并发修改
 
正确使用FileChannel的锁机制可以有效地管理对共享文件的并发访问,保证数据的一致性和完整性。