You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
        }
    }
}

关键说明

  1. 共享锁的作用:共享锁允许其他进程以读模式打开文件(支持复制操作),但阻止其他进程获取排他锁或删除文件(Windows下直接禁止删除,Linux下延迟删除)。
  2. 保持通道打开:必须确保文件通道在锁定期间处于打开状态,一旦通道关闭,锁会自动释放,文件就可以被删除了。
  3. 操作系统差异:不同系统的文件锁行为略有不同,需要在目标系统上测试验证:
    • Windows:文件被锁定时,无法删除、修改,只能读取/复制。
    • Linux:文件可以被rm命令标记为删除,但实际删除会等到所有打开的文件句柄关闭后才执行。

内容的提问来源于stack exchange,提问作者Den Didyk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:53:25