Java实现文件防删除但允许复制的锁定与解锁方法
Java实现文件锁定:阻止删除但允许复制
你当前使用FileLock.lock()获取的是排他锁,在Windows系统中,这种锁会直接阻止其他进程打开文件进行读取(包括复制操作),这就是复制被禁止的原因。要实现“阻止文件被删除,但允许正常复制”的需求,需要利用共享读锁,同时保持文件句柄处于打开状态——大多数操作系统中,只要有进程打开了文件,就无法直接删除它(Linux下是延迟删除,直到所有句柄关闭才会真正删除,Windows下则直接禁止删除)。
修改方案
将原来的排他锁改为共享锁,通过FileLock.lock(0L, Long.MAX_VALUE, true)方法获取,第三个参数true表示这是一个共享读锁。同时保持文件通道打开,直到解锁时再关闭。
修改后的完整代码
import java.io.File; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.util.ArrayList; import java.util.HashMap; public class FileLockDemo { public static void main(String[] args) { ArrayList<File> files = new ArrayList<>(); files.add(new File("C:\\Work\\Test\\a.txt")); files.add(new File("C:\\Work\\Test\\b.txt")); files.add(new File("C:\\Work\\Test\\c.txt")); HashMap<String, FileChannel> channelMap = lockFiles(files); if (channelMap == null) { System.err.println("锁定文件失败"); return; } try { // 模拟空闲,手动测试复制和删除操作 Thread.sleep(15000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } // 逐一解锁文件 channelMap.forEach((fileName, channel) -> { unlockFile(channel); System.out.println(fileName + " 已解锁"); try { Thread.sleep(5000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } private static HashMap<String, FileChannel> lockFiles(ArrayList<File> files) { HashMap<String, FileChannel> channelMap = new HashMap<>(); for (File file : files) { try { // 以只读模式打开文件,获取共享锁 RandomAccessFile raf = new RandomAccessFile(file, "r"); FileChannel channel = raf.getChannel(); // 获取整个文件的共享锁 FileLock lock = channel.lock(0L, Long.MAX_VALUE, true); // 保存通道,不要关闭,关闭通道会自动释放锁 channelMap.put(file.getName(), channel); System.out.println(file.getName() + " 已锁定"); } catch (Exception ex) { ex.printStackTrace(); // 锁定失败时,关闭已打开的通道 channelMap.values().forEach(ch -> { try { ch.close(); } catch (Exception e) { e.printStackTrace(); } }); return null; } } return channelMap; } private static void unlockFile(FileChannel channel) { try { if (channel != null && channel.isOpen()) { // 关闭通道会自动释放对应的FileLock channel.close(); System.out.println("已解锁"); } } catch (Exception ex) { ex.printStackTrace(); } } }
关键说明
- 共享锁的作用:共享锁允许其他进程以读模式打开文件(支持复制操作),但阻止其他进程获取排他锁或删除文件(Windows下直接禁止删除,Linux下延迟删除)。
- 保持通道打开:必须确保文件通道在锁定期间处于打开状态,一旦通道关闭,锁会自动释放,文件就可以被删除了。
- 操作系统差异:不同系统的文件锁行为略有不同,需要在目标系统上测试验证:
- Windows:文件被锁定时,无法删除、修改,只能读取/复制。
- Linux:文件可以被
rm命令标记为删除,但实际删除会等到所有打开的文件句柄关闭后才执行。
内容的提问来源于stack exchange,提问作者Den Didyk
相关产品推荐
相关产品推荐

