【问题标题】:Check if file is already open检查文件是否已经打开
【发布时间】:2019-09-17 16:22:48
【问题描述】:

我需要编写一个自定义批处理文件重命名器。我已经完成了大部分工作,只是我不知道如何检查文件是否已经打开。我只是使用java.io.File 包并且有一个canWrite() 方法,但这似乎并不能测试该文件是否正在被另一个程序使用。关于如何完成这项工作的任何想法?

【问题讨论】:

  • 这取决于平台。这是用于什么平台的?
  • 刚刚重新标记了您的问题,因为您可能必须通过使用 JNI 或 JNA 调用 WinAPI 来做到这一点。
  • 可能,但我们不要急于求成
  • 即使你知道它是开放的,也有一个竞赛条件可以用它做任何事情。

标签: java file-io


【解决方案1】:

使用 Apache Commons IO 库...

boolean isFileUnlocked = false;
try {
    org.apache.commons.io.FileUtils.touch(yourFile);
    isFileUnlocked = true;
} catch (IOException e) {
    isFileUnlocked = false;
}

if(isFileUnlocked){
    // Do stuff you need to do with a file that is NOT locked.
} else {
    // Do stuff you need to do with a file that IS locked
}

【讨论】:

  • 这不会对 .xls 文件抛出任何异常,触手可及。
  • 比赛状态警报!
  • 这将更改文件的最后修改日期和时间。
【解决方案2】:

(Q&A 是关于如何处理 Windows“打开文件”锁......而不是如何实现这种可移植的锁定。)

整个问题充满了可移植性问题和竞争条件:

  • 您可以尝试使用 FileLock,但您的操作系统和/或文件系统不一定支持它。
  • 在 Windows 上,如果其他应用程序以特定方式打开文件,您可能无法使用 FileLock。
  • 即使您确实设法使用了FileLock 或其他东西,您仍然会遇到问题,即在您测试文件和进行重命名之间,可能会有东西进入并打开文件。

一个更简单但不可移植的解决方案是尝试重命名(或您尝试执行的任何操作)并诊断返回值和/或由于打开文件而出现的任何 Java 异常。

注意事项:

  1. 如果您使用Files API 而不是File API,您将在发生故障时获得更多信息。

  2. 在允许重命名锁定或打开文件的系统(例如 Linux)上,您不会得到任何失败结果或异常。手术就会成功。但是,在此类系统上,您通常无需担心文件是否已打开,因为操作系统不会锁定打开的文件。

【讨论】:

    【解决方案3】:
        //  TO CHECK WHETHER A FILE IS OPENED 
        //  OR NOT (not for .txt files)
    
        //  the file we want to check
        String fileName = "C:\\Text.xlsx";
        File file = new File(fileName);
    
        // try to rename the file with the same name
        File sameFileName = new File(fileName);
    
        if(file.renameTo(sameFileName)){
            // if the file is renamed
            System.out.println("file is closed");    
        }else{
            // if the file didnt accept the renaming operation
            System.out.println("file is opened");
        }
    

    【讨论】:

    • 简直是天才! +1。
    • 不适用于 Linux。在 POSIX 文件系统中,文件名不是主键,而是指向文件内容的链接。因此,您可以重命名或删除打开的文件。没有人得到任何错误。
    • 可以确认这适用于 Windows10。似乎比引发异常要优雅得多。不适用于带有 ext4 的 linux。
    【解决方案4】:

    在 Windows 上,我使用

    找到了答案 https://stackoverflow.com/a/13706972/3014879

    fileIsLocked = !file.renameTo(file)

    最有用,因为它在处理写保护(或只读)文件时避免误报。

    【讨论】:

    • 谢谢。这是最有效和正确的答案。
    【解决方案5】:

    org.apache.commons.io.FileUtils.touch(yourFile) 不会检查您的文件是否打开。相反,它将文件的时间戳更改为当前时间。

    我使用了 IOException,它工作得很好:

    try 
    {
      String filePath = "C:\sheet.xlsx";
      FileWriter fw = new FileWriter(filePath );                
    }
    catch (IOException e)
    {
        System.out.println("File is open");
    }
    

    【讨论】:

    • 对正常控制流使用异常被认为是一种不好的做法。此外,在不产生异常的情况下,您最终可能会打开 fw
    • 为此我可以最终使用,因此文件将以两种方式关闭 FileWriter fw;尝试 { String filePath = "C:\sheet.xlsx"; fw = new FileWriter(filePath); } catch (IOException e) { System.out.println("文件已打开"); } 最后 { fw.close(); }
    【解决方案6】:

    我认为你永远不会得到一个明确的解决方案,操作系统不一定会告诉你文件是否打开。

    您可能会从 java.nio.channels.FileLock 中获得一些好处,尽管 javadoc 加载了一些警告。

    【讨论】:

    • 是的,不能保证底层操作系统,甚至文件系统,以任何合理的方式支持文件锁。
    【解决方案7】:

    您好,我真的希望这会有所帮助。

    我之前尝试了所有选项,但没有一个真正适用于 Windows。帮助我完成此任务的唯一想法是尝试移动文件。事件到 ATOMIC_MOVE 下的同一个地方。如果文件是由另一个程序或Java线程写入的,这肯定会产生异常。

     try{
    
          Files.move(Paths.get(currentFile.getPath()), 
                   Paths.get(currentFile.getPath()), StandardCopyOption.ATOMIC_MOVE);
    
          // DO YOUR STUFF HERE SINCE IT IS NOT BEING WRITTEN BY ANOTHER PROGRAM
    
     } catch (Exception e){
    
          // DO NOT WRITE THEN SINCE THE FILE IS BEING WRITTEN BY ANOTHER PROGRAM
    
     }
    

    【讨论】:

      【解决方案8】:

      如果文件正在使用 FileOutputStream fileOutputStream = new FileOutputStream(file); 返回 java.io.FileNotFoundException 异常消息中的“进程无法访问该文件,因为它正被另一个进程使用”。

      【讨论】:

      • 我会感谢 cmets 关于投票的原因
      • 如果文件未被使用,则用零字节覆盖文件内容,因此它基本上删除了文件。适用于 linux (ext4) 和 Win10。第三次投反对票是我的。
      • 当我使用 FileOutputStream fileOutputStream = new FileOutputStream(file) 时出现此异常
      猜你喜欢
      • 2019-04-29
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-28
      • 2016-07-15
      • 1970-01-01
      相关资源
      最近更新 更多