如何在 Java 中实现文件防删除但允许复制的独占锁机制

云宇酱_3410

云宇酱_3410

2026-11-06

666人浏览

原创

如何在 Java 中实现文件防删除但允许复制的独占锁机制

本文介绍如何使用 Java 的 FileLock 实现“仅阻止删除、不限制读取与复制”的文件锁定策略,核心是采用共享锁(shared lock)配合只读通道,避免阻塞其他进程的复制操作。

本文介绍如何使用 java 的 `filelock` 实现“仅阻止删除、不限制读取与复制”的文件锁定策略,核心是采用共享锁(shared lock)配合只读通道,避免阻塞其他进程的复制操作。

在 Windows 等主流操作系统中,文件删除行为本质上依赖于对父目录的写权限,而非文件本身是否被打开;但若某进程以独占方式(exclusive)打开并锁定文件(如 RandomAccessFile("rw") + channel.lock()),Windows 会拒绝其他进程对该文件执行删除、重命名甚至部分复制操作(因复制工具常尝试以写模式打开目标或临时文件,触发锁冲突)。这正是你遇到的问题:FileLock 默认为排他锁,导致 copy 命令或资源管理器复制失败。

要达成「防删除但允复制」的目标,关键在于:不阻止文件读取,仅确保文件句柄持续被持有——从而防止操作系统释放其 inode/引用计数,使外部删除操作因“文件正被占用”而失败。此时应使用 共享读锁(shared lock)+ 只读文件通道,它允许任意数量的其他进程同时以只读方式打开该文件(包括复制工具),但只要你的 JVM 进程保持锁有效,系统就无法真正删除该文件(在 Windows 上表现为“文件正在被另一个程序使用”)。

以下是符合需求的完整实现方案:

import java.io.IOException;
import java.nio.channels.*;
import java.nio.file.*;
import java.util.*;

public class FileDeletionGuard {

    private final Map<string filelock> activeLocks = new HashMap();
    private final Map<string filechannel> openChannels = new HashMap();

    /**
     * 对指定文件加共享读锁(防删除,允复制/读取)
     * @param files 待保护的文件列表
     * @return 成功锁定的文件名 → FileLock 映射
     */
    public Map<string filelock> lockFiles(List<path> files) {
        Map<string filelock> locks = new HashMap();
        for (Path path : files) {
            try {
                // 仅以 READ 模式打开,确保兼容性与最小干扰
                FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
                // 获取共享锁(第三个参数 true 表示 shared)
                FileLock lock = channel.lock(0, Long.MAX_VALUE, true);

                String fileName = path.getFileName().toString();
                locks.put(fileName, lock);
                activeLocks.put(fileName, lock);
                openChannels.put(fileName, channel);
                System.out.println("✅ Locked for deletion protection: " + fileName);
            } catch (IOException e) {
                System.err.println("❌ Failed to lock " + path + ": " + e.getMessage());
            }
        }
        return locks;
    }

    /**
     * 解锁并关闭对应通道
     */
    public void unlockFile(String fileName) {
        FileLock lock = activeLocks.remove(fileName);
        FileChannel channel = openChannels.remove(fileName);
        if (lock != null && channel != null) {
            try {
                lock.release();
                channel.close();
                System.out.println("? Unlocked: " + fileName);
            } catch (IOException e) {
                System.err.println("⚠️  Error releasing lock for " + fileName + ": " + e.getMessage());
            }
        }
    }

    /**
     * 批量解锁所有已锁定文件
     */
    public void unlockAll() {
        List<string> keys = new ArrayList(activeLocks.keySet());
        for (String fileName : keys) {
            unlockFile(fileName);
        }
    }
}</string></string></path></string></string></string>

使用示例:

Java调试
Java调试

通过 JDWP 实现 Java 远程调试:连接远程 JVM、设置断点、单步执行代码、查看变量值、获取调用栈。适用于需要调试远程 Java 应用、排查运行时状态、追踪代码执行流程的场景。 术语注解 JDWP:Java Debug Wire Protocol,Java 调试有线协议(Java 远程调试底层通信协议) remote JVM:远程 Java 虚拟机 step through code:代码单步调试(步入 / 步过 / 步出调试) inspect variables:变量查看 / 变量检视 stac

下载
public static void main(String[] args) {
    List<path> files = Arrays.asList(
        Paths.get("C:\Work\Test\a.txt"),
        Paths.get("C:\Work\Test\b.txt"),
        Paths.get("C:\Work\Test\c.txt")
    );

    FileDeletionGuard guard = new FileDeletionGuard();
    Map<string filelock> locks = guard.lockFiles(files);

    // 持续保护 15 秒(可手动测试:尝试删除/复制这些文件)
    try {
        Thread.sleep(15_000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }

    // 逐一解锁
    locks.forEach((name, lock) -> {
        guard.unlockFile(name);
        try { Thread.sleep(5_000); } catch (InterruptedException e) { }
    });
}</string></path>

✅ 效果验证说明:

  • ✅ 其他进程可正常复制(copy a.txt a_copy.txt)、读取(记事本打开)、甚至用 robocopy 或 PowerShell Copy-Item;
  • ❌ 尝试删除(del a.txt 或资源管理器右键删除)将失败,并提示“文件正被另一个程序使用”;
  • ⚠️ 注意:此机制 不能防止管理员级强制删除(如 takeown + icacls 修改权限后删除)或文件系统级操作(如磁盘格式化),它仅提供应用层协作式保护。

? 重要注意事项:

  • FileLock 是建议性锁(advisory),仅对同样使用 FileLock 的进程生效;恶意或不遵循规范的程序仍可能绕过(但普通用户操作和标准工具均受约束);
  • 锁定范围设为 0 ~ Long.MAX_VALUE 表示全文件锁定,确保删除操作被拦截;
  • 必须显式调用 lock.release() 和 channel.close(),否则可能导致句柄泄漏或锁残留;
  • Linux/macOS 下行为略有差异(如 unlink 可能成功但文件内容保留至所有句柄关闭),本方案在 Windows 上效果最稳定,符合常见企业环境需求。

通过共享读锁这一轻量、标准且跨 JDK 版本兼容的方式,你无需 JNI 或第三方库,即可稳健实现“防删不禁读”的文件保护目标。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

12037

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

9122

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

7812

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1264

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

1028

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1516

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

3149

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20391

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1375

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习