检查文件是否在 Java 中被锁定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1500174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 13:31:19  来源:igfitidea点击:

Check if a file is locked in Java

javalocking

提问by Hellnar

My Java program wants to read a file which can be locked by another program writing into it. I need to check if the file is locked and if so wait until it is free. How do I achieve this?

我的 Java 程序想要读取一个文件,该文件可以被另一个写入它的程序锁定。我需要检查文件是否被锁定,如果是,请等到它空闲。我如何实现这一目标?

The Java program is running on a Windows 2000 server.

Java 程序在 Windows 2000 服务器上运行。

采纳答案by jarnbjo

Under Windows with Sun's JVM, the FileLocks should work properly, although the JavaDocs leave the reliability rather vague (system dependent).

在带有 Sun JVM 的 Windows 下,FileLocks 应该可以正常工作,尽管 JavaDocs 的可靠性相当模糊(依赖于系统)。

Nevertheless, if you only have to recognize in your Java program, that some otherprogram is locking the file, you don't have to struggle with FileLocks, but can simply try to write to the file, which will fail if it is locked. You better try this on your actual system, but I see the following behaviour:

然而,如果您只需要在您的 Java 程序中识别出某个其他程序正在锁定该文件,您就不必与 FileLocks 斗争,而可以简单地尝试写入该文件,如果它被锁定,这将失败。你最好在你的实际系统上试试这个,但我看到以下行为:

File f = new File("some-locked-file.txt");
System.out.println(f.canWrite()); // -> true
new FileOutputStream(f); // -> throws a FileNotFoundException

This is rather odd, but if you don't count platform independence too high and your system shows the same behaviour, you can put this together in a utility function.

这很奇怪,但是如果您不认为平台独立性太高并且您的系统显示相同的行为,您可以将其放在一个实用程序函数中。

With current Java versions, there is unfortunately no way to be informed about file state changes, so if you need to wait until the file can be written, you have to try every now and then to check if the other process has released its lock. I'm not sure, but with Java 7, it might be possible to use the new WatchService to be informed about such changes.

对于当前的 Java 版本,遗憾的是无法获知文件状态的变化,因此如果您需要等到可以写入文件时,您必须时不时地尝试检查其他进程是否已释放其锁。我不确定,但是在 Java 7 中,可能可以使用新的 WatchService 来了解此类更改。

回答by Ben S

Use a FileLockin all the Java applications using that file and have them run within the same JVM. Otherwise, this can't be done reliably.

FileLock在使用该文件的所有 Java 应用程序中使用 a并让它们在同一个 JVM 中运行。否则,这不能可靠地完成。

回答by erickson

If multiple processes (which can be a mix of Java and non-Java) might be using the file, use a FileLock. A key to using file locks successfully is to remember that they are only "advisory". The lock is guaranteed to be visible if you check for it, but it won't stop you from doing things to the file if you forget. All processes that access the file should be designed to use the locking protocol.

如果多个进程(可以是 Java 和非 Java 的混合)可能正在使用该文件,请使用FileLock. 成功使用文件锁的一个关键是记住它们只是“建议”。如果您检查该锁,则保证它是可见的,但如果您忘记了,它不会阻止您对文件进行操作。所有访问文件的进程都应该设计为使用锁定协议。

回答by Ruben Faelens

You can try to get an exclusive lock on the file. As long as the exclusive lock cannot be obtained, another program has a lock (exclusive or shared) on the file.

您可以尝试获取文件的排他锁。只要无法获得排他锁,另一个程序就会对该文件进行锁定(排他或共享)。

回答by Vlad

Should work in Windows:

应该在 Windows 中工作:

File file = new File("file.txt");
boolean fileIsNotLocked = file.renameTo(file);

回答by venergiac

The best way is to use FileLock, but in my case (jdk 1.6) I tried with success:

最好的方法是使用 FileLock,但就我而言(jdk 1.6),我尝试成功:

public static boolean isFileUnlocked(File file) {
        try {
            FileInputStream in = new FileInputStream(file);
            if (in!=null) in.close();
            return true;
        } catch (FileNotFoundException e) {
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

回答by Amjad Abdul-Ghani

Tested on windows only : you can check if the file is locked as following enhanced venergiacanswer: check for (file.exist()) file exists but with FileNotFoundException means is locked! you will notice this message (The process cannot access the file because it is being used by another process)

仅在 Windows 上测试:您可以按照以下增强的venergiac答案检查文件是否被锁定:检查 (file.exist()) 文件是否存在,但 FileNotFoundException 表示已锁定!您会注意到此消息(该进程无法访问该文件,因为它正被另一个进程使用)

        public static boolean isFilelocked(File file) {
                try {

                    FileInputStream in = new FileInputStream(file);
                    in.close();
                    return false;
                } catch (FileNotFoundException e) {
                    if(file.exist()){ 
                       return true;
                     }
                     return false;
                } catch (Exception e) {
                    e.printStackTrace();
                }

                return false;
            }

回答by Brook

Improved Amjad Abdul-Ghani answer, I found that no error was produced until attempting to read from the file

改进了 Amjad Abdul-Ghani 的回答,我发现在尝试从文件中读取之前没有产生错误

public static boolean isFilelocked(File file) {
     try {
         try (FileInputStream in = new FileInputStream(file)) {
             in.read();
             return false;
         }
     } catch (FileNotFoundException e) {
         return file.exists();
     } catch (IOException ioe) {
         return true;
     }
 }

回答by Claudio

I tryed combination of answers (@vlad) on windows with access to Linux Smb share and it worked for me. The first part was enough for lock like Excel but not for some editors. I added second part (rename) for testing both situations.

我尝试在 Windows 上组合答案 (@vlad) 并访问 Linux Smb 共享,它对我有用。第一部分对于像 Excel 这样的锁定来说已经足够了,但对于某些编辑器来说却不够。我添加了第二部分(重命名)来测试这两种情况。

public static boolean testLockFile(File p_fi) {
    boolean bLocked = false;
    try (RandomAccessFile fis = new RandomAccessFile(p_fi, "rw")) {
      FileLock lck = fis.getChannel().lock();
      lck.release();
    } catch (Exception ex) {
      bLocked = true;
    }
    if (bLocked)
      return bLocked;
    // try further with rename
    String parent = p_fi.getParent();
    String rnd = UUID.randomUUID().toString();
    File newName = new File(parent + "/" + rnd);
    if (p_fi.renameTo(newName)) {
      newName.renameTo(p_fi);
    } else
      bLocked = true;
    return bLocked;
  }

回答by Dimitar II

For Windows, you can also use:

对于 Windows,您还可以使用:

new RandomAccessFile(file, "rw")

If the file is exclusively locked (by MS Word for example), there will be exception: java.io.FileNotFoundException: <fileName> (The process cannot access the file because it is being used by another process). This way you do not need to open/close streams just for the check.

如果文件被独占锁定(例如通过 MS Word),则会出现异常: java.io.FileNotFoundException: <fileName> (The process cannot access the file because it is being used by another process). 这样你就不需要为了检查而打开/关闭流。

Note - if the file is not exclusively locked (say opened in Notepad++) there will be no exception.

注意 - 如果文件没有被独占锁定(比如在 Notepad++ 中打开),也不会有例外。