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

大晨吖_2195

大晨吖_2195

2026-11-06

456人浏览

原创

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

本文介绍如何使用 Java 的共享文件锁(shared lock)实现对文件的保护:阻止其他进程删除文件,同时不影响其被正常读取或复制,通过 lock() 和 unlock() 方法封装控制逻辑。

本文介绍如何使用 java 的共享文件锁(shared lock)实现对文件的保护:阻止其他进程删除文件,同时不影响其被正常读取或复制,通过 `lock()` 和 `unlock()` 方法封装控制逻辑。

在 Windows 系统中,文件能否被删除取决于其是否被任何进程以独占(exclusive)方式打开。若一个进程以写入模式(如 "rw")获取了 FileChannel 并加锁,该锁默认为排他锁(exclusive),不仅会阻止其他进程修改/写入,还会导致 Windows 拒绝删除操作——同时也可能干扰复制行为(尤其在资源管理器等工具中,因部分复制流程会尝试临时独占打开源文件)。

而真正的解决方案是:仅以只读方式打开文件,并施加共享锁(shared lock)。共享锁允许多个进程同时持有,它不会阻止其他进程读取、复制,但能有效防止文件被删除(因为 Windows 要求文件在无任何打开句柄时才可删除;共享读锁即构成一个“打开句柄”)。

以下是推荐的实现方式:

Java调试
Java调试

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

下载

✅ 正确做法:使用 FileChannel.open() + 共享锁(true 参数)

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

public class FileGuard {

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

    /**
     * 对指定文件列表加共享读锁(防删除,不限制复制/读取)
     */
    public static Map<string filelock> lockFiles(List<path> paths) {
        Map<string filelock> locks = new HashMap();
        for (Path path : paths) {
            try {
                // 仅以 READ 模式打开,申请共享锁(第三个参数 true)
                FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
                FileLock lock = channel.lock(0, Long.MAX_VALUE, true); // 共享锁
                locks.put(path.getFileName().toString(), lock);
                activeLocks.put(path.toString(), lock);
                System.out.println("✅ Shared lock acquired on: " + path);
            } catch (IOException e) {
                System.err.println("❌ Failed to lock " + path + ": " + e.getMessage());
            }
        }
        return locks;
    }

    /**
     * 释放指定锁并关闭对应通道
     */
    public static void unlockFile(FileLock lock) {
        if (lock == null || lock.isValid()) {
            try {
                lock.release();
                lock.channel().close();
                System.out.println("? Lock released");
            } catch (IOException e) {
                System.err.println("⚠️  Error releasing lock: " + e.getMessage());
            }
        }
    }

    /**
     * 批量解锁(推荐用于 cleanup)
     */
    public static void unlockAll() {
        activeLocks.values().forEach(FileGuard::unlockFile);
        activeLocks.clear();
    }
}</string></path></string></string>

? 使用示例

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

    Map<string filelock> locks = FileGuard.lockFiles(files);

    // 模拟守护期(期间文件不可删除,但可复制、读取)
    try {
        Thread.sleep(15_000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }

    // 逐一释放
    locks.forEach((name, lock) -> {
        FileGuard.unlockFile(lock);
        System.out.println(name + " unlocked");
        try { Thread.sleep(5000); } catch (InterruptedException ignored) {}
    });
}</string></path>

⚠️ 关键注意事项

  • 仅 Windows 有效:该机制依赖 Windows 文件系统语义(删除需关闭所有句柄)。Linux/macOS 不强制要求“无打开句柄才能删除”,因此此方案主要适用于 Windows 环境。
  • 锁生命周期绑定通道:FileLock 必须与 FileChannel 配合使用,且 channel.close() 后锁自动失效;务必确保 unlockFile() 中先 release() 再 close()。
  • 不要混用 RandomAccessFile 和 FileChannel.open():前者易误开写模式,后者更可控、更符合现代 NIO 最佳实践。
  • 异常处理不可省略:I/O 操作必须捕获 IOException,避免锁泄漏;建议配合 try-with-resources(如示例中 FileChannel.open(...) 可进一步优化为自动关闭)。
  • 进程退出前务必调用 unlockAll():防止残留锁导致后续启动失败。

✅ 总结

要实现「防删除但允复制」,核心不是“加更强的锁”,而是“加更轻量、更兼容的锁”——即只读共享锁。它既满足操作系统级的删除防护要求,又完全兼容复制、备份、文本编辑器查看等常规操作。结合清晰的 lockFiles() / unlockFile() 封装,即可构建稳定可靠的文件保护模块。

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

相关专题

更多
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人学习