文件锁如何工作?

2024-04-08

我一直在尝试使用FileLock获得对文件的独占访问权限,以便:

  • 删除它
  • 重命名它
  • 写信给它

因为在 Windows 上(至少),您似乎无法删除、重命名或写入已在使用的文件。我写的代码看起来像这样:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public abstract class LockedFileOperation {

    public void execute(File file) throws IOException {

        if (!file.exists()) {
            throw new FileNotFoundException(file.getAbsolutePath());
        }

        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

        try {
            // Get an exclusive lock on the whole file
            FileLock lock = channel.lock();

            try {
                doWithLockedFile(file);
            } finally {
                lock.release();
            }
        } finally {
            channel.close();
        }
    }

    public abstract void doWithLockedFile(File file) throws IOException;
}

以下是一些演示该问题的单元测试。您需要在类路径上安装 Apache commons-io 才能运行第三个测试。

import java.io.File;
import java.io.IOException;

import junit.framework.TestCase;

public class LockedFileOperationTest extends TestCase {

    private File testFile;

    @Override
    protected void setUp() throws Exception {

        String tmpDir = System.getProperty("java.io.tmpdir");
        testFile = new File(tmpDir, "test.tmp");

        if (!testFile.exists() && !testFile.createNewFile()) {
            throw new IOException("Failed to create test file: " + testFile);
        }
    }

    public void testRename() throws IOException {
        new LockedFileOperation() {

            @Override
            public void doWithLockedFile(File file) throws IOException {
                if (!file.renameTo(new File("C:/Temp/foo"))) {
                    fail();
                }
            }
        }.execute(testFile);
    }

    public void testDelete() throws IOException {
        new LockedFileOperation() {

            @Override
            public void doWithLockedFile(File file) throws IOException {
                if (!file.delete()) {
                    fail();
                }
            }
        }.execute(testFile);
    }

    public void testWrite() throws IOException {
        new LockedFileOperation() {

            @Override
            public void doWithLockedFile(File file) throws IOException {
                org.apache.commons.io.FileUtils.writeStringToFile(file, "file content");
            }
        }.execute(testFile);
    }
}

所有测试均未通过。前两个失败,最后一个抛出此异常:

java.io.IOException: The process cannot access the file because another process has locked a portion of the file
    at java.io.FileOutputStream.writeBytes(Native Method)
    at java.io.FileOutputStream.write(FileOutputStream.java:247)
    at org.apache.commons.io.IOUtils.write(IOUtils.java:784)
    at org.apache.commons.io.IOUtils.write(IOUtils.java:808)
    at org.apache.commons.io.FileUtils.writeStringToFile(FileUtils.java:1251)
    at org.apache.commons.io.FileUtils.writeStringToFile(FileUtils.java:1265)

似乎是lock()方法在文件上加锁,然后阻止我重命名/删除/写入它。我的假设是锁定文件将使我能够独占访问该文件,因此我可以重命名/删除/写入它,而不必担心是否有任何其他进程也在访问它。

要么是我误会FileLock或者这不是解决我的问题的合适方法。


有关另一个进程的消息仅意味着您系统上的某个进程打开了该文件。它实际上并不检查该进程是否与尝试删除/重命名文件的进程相同。在这种情况下,同一程序打开了该文件。您已打开它以获取锁。这里的锁几乎没有价值,特别是当您执行删除或重命名操作时。

要执行您想要的操作,您需要锁定目录条目。这在 Java 中不可用,在 Windows 中也可能不可用。这些(删除和插入)操作是原子操作。这意味着操作系统会为您锁定目录和其他文件系统结构。如果另一个进程(或您自己的进程)打开了该文件,那么这些操作将失败。如果您尝试以独占方式锁定文件(目录项),而另一个进程(或您自己的进程)打开了该文件,则锁定将失败。没有什么区别,但尝试执行锁定只会使操作变得复杂,并且在这种情况下,会使操作变得不可能(即,在尝试执行操作之前文件总是打开的)。

现在写入文件是一个有效的锁定操作。锁定要写入的文件或文件的一部分,然后它就会起作用。在 Windows 上,此锁定机制是强制性的,因此另一个打开/文件描述符将无法写入锁定下的任何部分。

EDIT

根据 JavaDoc 上FileChannel.lock,这与调用相同FileChannel.lock(0L, Long.MAXVALUE, false)。这是从第一个字节到最后一个字节的区域的独占锁。

其次,根据JavaDocFileLock

锁是否实际上阻止另一个程序访问锁定区域的内容取决于系统,因此未指定。某些系统的本机文件锁定功能仅仅是建议性的,这意味着程序必须协同遵守已知的锁定协议才能保证数据完整性。在其他系统上,本机文件锁是强制性的,这意味着如果一个程序锁定文件的某个区域,那么实际上会阻止其他程序以违反锁定的方式访问该区域。在其他系统上,本机文件锁是建议性的还是强制的,都可以根据每个文件进行配置。为了确保跨平台行为一致且正确,强烈建议将此 API 提供的锁用作咨询锁.

EDIT

For the testWrite方法。关于公共 I/O 静态方法的 JavaDoc 很稀疏,但说“将字符串写入创建文件的文件,如果它不存在......”并且因为此方法需要一个File它可能在内部打开文件,而不是打开的流。可能它没有以共享访问方式打开文件,也没有以追加访问方式打开文件。这意味着现有的打开和锁定(您打开以获取从中获取锁定的通道)正在阻止该使用。要了解更多信息,您需要获取该方法的源代码并查看它正在做什么。

EDIT

抱歉,我纠正了。我检查了 Windows API,发现文件锁定在 Windows 上是强制的。这就是写入失败的原因。第一个打开(您的new RandomAccessFile) 并且 lock 已锁定文件。打开写入字符串成功,但写入失败,因为另一个打开(文件描述符)在强制排它锁下拥有文件的完整范围 - 也就是说,在释放锁之前,没有其他文件描述符可以写入该文件。

请注意,锁定与文件描述符相关联NOT进程或线程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

文件锁如何工作? 的相关文章

  • HashMap不写入数据库

    我尝试在我的数据库中写入 但只写入发件人和消息 我不明白为什么会发生这种情况 我认为问题出在我使用 sendMessage 的地方 我认为问题是我没有什么可以做的读 写其他用户的主键 我在数据库中写入消息的活动 public class M
  • 对话框上的 EditText 不返回任何文本

    我太累了 找不到错误 我没有发现任何错误 但我没有从 editText 收到任何文本 请看下面的代码 活动密码 xml
  • Spring安全“记住我”cookie在第一个请求中不可用

    我无法在登录请求后检索 Spring 记住我 cookie 但它在对受保护页面的下一个请求中工作正常 谁能告诉我怎样才能立即得到它 我在登录请求中设置了记住我的 cookie 但在 Spring 重定向回原始 受保护的 url 后无法检索它
  • Java:使用 HttpURLConnection 的 HTTP PUT

    如何执行 HTTP PUT 我正在使用的类似乎认为它正在执行 PUT 但端点将其视为我执行了 GET 我做错了什么吗 URL url new URL https HttpURLConnection conn HttpURLConnectio
  • eclipse中导入项目文件夹图标

    我在 Eclipse 工作区中新导入的 Maven 项目有J and M项目文件夹顶部的图标 项目和包资源管理器 而其他导入的 Maven 项目只有一个J icon 有人可以解释其中的区别吗 该项目有J装饰器被称为 Java 项目和具有M装
  • 如何在 JSP 中导入类?

    我是一个完全的JSP初学者 我正在尝试使用java util List在 JSP 页面中 我需要做什么才能使用除以下类之外的类java lang 使用以下导入语句进行导入java util List 顺便说一句 要导入多个类 请使用以下格式
  • 在 HTTP 标头中发送 UTF-8 值会导致 Mojibake

    我想使用 servlet 发送阿拉伯语数据HTTPServletResponse给客户 我正在尝试这个 response setCharacterEncoding UTF 8 response setHeader Info arabicWo
  • 记录骆驼路线

    我的项目中有几个 Camel 上下文 如果可能的话 我想以逆向工程方式记录路线 因为我们希望保持与上下文相关的文档最新 最好的方法是什么 我们倾向于预先实际设计路线 并使用来自EIP book http www eaipatterns co
  • 如何从 Retrofit2 获取字符串响应?

    我正在做 android 正在寻找一种方法来执行超级基本的 http GET POST 请求 我不断收到错误 java lang IllegalArgumentException Unable to create converter for
  • 如何将 android.net.Uri 转换为 java.net.URL? [复制]

    这个问题在这里已经有答案了 有没有办法从Uri to URL 我正在使用的库需要这个 它only接受一个URL但我需要在我的设备上使用图像 如果该方案的Uri is http or https new URL uri toString 应该
  • 具有共享依赖项的多模块项目的 Gradle 配置

    使用 gradle 制作第一个项目 所以我研究了 spring gradle hibernate 项目如何组织 gradle 文件 并开始制作自己的项目 但是 找不到错误 为什么我的配置不起作用 子项目无法解决依赖关系 所以项目树 Root
  • Cloudfoundry:如何组合两个运行时

    cloundfoundry 有没有办法结合两个运行时环境 我正在将 NodeJS 应用程序部署到 IBM Bluemix 现在 我还希望能够执行独立的 jar 文件 但应用程序失败 APP 0 bin sh 1 java not found
  • Spring Security OAuth2简单配置

    我有一个简单的项目 需要以下简单的配置 我有一个 密码 grant type 这意味着我可以提交用户名 密码 用户在登录表单中输入 并在成功时获得 access token 有了该 access token 我就可以请求 API 并获取用户
  • 在 Spring Boot Actuator 健康检查 API 中启用日志记录

    我正在使用 Spring boot Actuator APIproject https imobilenumbertracker com 拥有一个健康检查端点 并通过以下方式启用它 management endpoints web base
  • 如何配置 WebService 返回 ArrayList 而不是 Array?

    我有一个在 jax ws 上实现的 java Web 服务 此 Web 服务返回用户的通用列表 它运行得很好 Stateless name AdminToolSessionEJB RemoteBinding jndiBinding Admi
  • Espresso 和 Proguard 的 Java.lang.NoClassDefFoundError

    我对 Espresso 不太有经验 但我终于成功地运行了它 我有一个应用程序需要通过 Proguard 缩小才能处于 56K 方法之下 该应用程序以 3 秒的动画开始 因此我需要等到该动画结束才能继续 这就是我尝试用该方法做的事情waitF
  • JVM:是否可以操作帧堆栈?

    假设我需要执行N同一线程中的任务 这些任务有时可能需要来自外部存储的一些值 我事先不知道哪个任务可能需要这样的值以及何时 获取速度要快得多M价值观是一次性的而不是相同的M值在M查询外部存储 注意我不能指望任务本身进行合作 它们只不过是 ja
  • 解决错误javax.mail.AuthenticationFailedException

    我不熟悉java中发送邮件的这个功能 我在发送电子邮件重置密码时遇到错误 希望你能给我一个解决方案 下面是我的代码 public synchronized static boolean sendMailAdvance String emai
  • 哪个集合更适合存储多维数组中的数据?

    我有一个multi dimensional array of string 我愿意将其转换为某种集合类型 以便我可以根据自己的意愿添加 删除和插入元素 在数组中 我无法删除特定位置的元素 我需要这样的集合 我可以在其中删除特定位置的数据 也
  • Android AutoCompleteTextView 带芯片

    我不确定我是否使用了正确的词语来描述此 UI 功能 但我已附上我希望在我的应用程序中实现的目标的快照 它由 Go SMS 使用 用户在编辑文本中键入联系人 在用户从完成下拉列表中选择联系人后 该联系人将被插入到编辑文本中 如附图所示 编辑文

随机推荐

  • 集中式和分布式版本控制系统之间的比较[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何让我的 tkinter 原型系统计算出正确的总价

    我是一名初学者 我正在使用 Tkinter 为 DIY 商店创建一个原型系统 作为我任务的一部分 该应用程序的工作原理是填写一份简单的调查来创建订单 单击 输入数据 按钮后 页面底部应显示您的选择结果 包括总价 我需要一些关于如何编写系统计
  • 使用 serde 序列化时如何按字母顺序对字段进行排序?

    我有一个 API 要求对象的字段按字母顺序排序 因为必须对结构进行哈希处理 在 Java Jackson 中 您可以在序列化器中设置一个标志 MapperFeature SORT PROPERTIES ALPHABETICALLY 我在 S
  • 聚合物全局变量

    我正在开发一个 Polymer 应用程序 它从 RESTful API 中提取数据并使用它来构建界面 我在概念上坚持的一个特定领域是单态模式的实现 描述于http www polymer project org docs polymer p
  • BigQueryTable.InsertRows 间歇性地抛出未找到表 xx

    我们只是删除表 创建表 然后使用插入数据 BigQueryTable table try table dataset GetTable tableName table Delete catch finally table dataset C
  • 如何在 .NET Framework 4.7.1 中使用 Azure KeyVault 覆盖 Web.config 值

    如何在 ASP NET Framework 4 7 1 WebForms 应用程序中实现 Microsoft 的 Azure KeyVault 以覆盖中的值web config使用 KeyVault 中的值 我确实看到参考资料表明我们需要最
  • Youtube iOS 播放器帮助程序库无法正常工作

    我尝试实现 youtube ios player helper 库来在我的应用程序中播放视频 我可以准备好播放器并加载视频 并且可以显示起始缩略图 但是 当我尝试播放视频时 却收到以下错误消息 SendDelegateMessage NSI
  • 通过尾指针添加到链表,无需 3 级间接

    我正在开发一个需要实现链表的项目 在开始这个项目之前 我正在回顾创建链表的经典方法 我意识到过去我一直通过head遍历列表直到到达空指针的指针 我发现没有必要这样做 并以涉及的方式实现它tail指针 但我能想到的唯一方法是涉及三重指针或全局
  • Jquery Multiselect:如何知道选择/取消选择哪个值

    我有多选下拉菜单 每当有选择或取消选择时 我都需要获取该值 我正在使用更改事件 但很难确定选择 取消选择了哪个选项 all options var all multiple each function i selected all i se
  • 如何在 C# 中附加 xml 文件?

    我正在为一个简单进程添加跟踪 以进行审计 我将其构建为 exe 并在调度程序中设置为每 10 分钟运行一次 我想让应用程序将结果输出到 xml 文件中 如果文件存在 则打开并向其追加数据 如果不存在 我想创建一个新的 xml 文件 该文件将
  • C/C++ 中的动态位向量

    我正在寻找一个可以使用的现成的 C 或 C 动态位向量 不幸的是 由于各种原因 我目前无法使用 BoostT 库 std bitvector 看起来很有希望 但它是模板化的 所以我无法动态设置位向量的长度 有人可以建议吗 谢谢 您不必仅仅为
  • 安装SSDT(SQL Server数据工具)时出错

    我在安装 SQL Server Data Tools for Visual Studio 2017 过程中遇到问题 我收到以下错误 已翻译 The requested meta file operation is not supported
  • SwiftUI:两个并排列表和一个导航视图出现意外行为

    我的屏幕有两个List并排 在一个NavigationView 布局渲染正确 我可以独立滚动两个列表 问题是 当我滚动第一个列表时 它位于导航栏后面 而没有触发对其应用背景颜色的效果 下面的 gif 展示了正在发生的事情 这是我用于此视图的
  • request.getSession() 在 sendRedirect() 之后创建新会话

    我们正在开发旅行应用程序 通过这个航班 可以预订酒店 巴士票 它是基于产品的应用程序 我们有近 25 个客户 3 个客户正在使用 其余仍在开发中 我们为所有客户维护一台服务器 一台服务器 应用程序 多个客户端是我的应用程序中的伟大成就 但问
  • 使用 jq 将 JSON 对象转换为 Prometheus 指标格式

    考虑一个 JSON 对象 例如 foo 42 baz 12 bar label1 value1 12 34 建造者jq https github com stedolan jq使用一些数据源 实际的键名称及其数量可能会有所不同 但结果将始终
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt
  • 在Python中的同一个图上绘制多个位置的年度数据[重复]

    这个问题在这里已经有答案了 我有几个站 20 年的数据框 我想以某种方式绘制它 x 轴是年份 y 轴是观测值 线条的颜色显示位置 station year observations 0 3939 2000 0 346518 1 3939 2
  • 通过 UDF 获取 Google 搜索第一个结果[重复]

    这个问题在这里已经有答案了 Santosh 对以下问题有一个很棒的答案 vba 代码 link https stackoverflow com questions 17495644 using vba in excel to google
  • 将 .NET 事件公开给 COM?

    我一直在尝试向 VBA 客户端公开并触发事件 到目前为止 在 VBA 客户端 事件已公开 并且我看到方法事件处理方法已添加到我的模块类中 但是 VBA 事件处理方法不会触发 由于某种原因 调试时事件为空 同步修改我的代码也没有帮助 作为记录
  • 文件锁如何工作?

    我一直在尝试使用FileLock获得对文件的独占访问权限 以便 删除它 重命名它 写信给它 因为在 Windows 上 至少 您似乎无法删除 重命名或写入已在使用的文件 我写的代码看起来像这样 import java io File imp