java - 如何使用 Java (openjdk 11) 在 Windows 10 中独占锁定文件?

标签 java windows-10 openjdk-11

我尝试使用 openjdk 11 在 Windows 10 中独占锁定文件,但它无法按预期工作。 它应该保证只要锁定到位,除了我自己的进程之外,没有任何进程应该能够编辑/删除/...该文件。

我寻找答案,但它们 a) 相当旧,b) 使用与我相同的代码,并说“这就是它是如何完成的”。

下面是一个简单的示例,它创建一个测试文件,并在获取锁定后等待 10 秒,然后再读取。非共享锁需要打开选项“WRITE”(否则 tryLock 会抛出 UnsupportedOperationException)。

到目前为止的行为:

  • 当我在等待期间删除文件(在 Windows 资源管理器中)时,读取仍会提供文件的原始内容,但在我删除文件时,文件就会从资源管理器概述中消失
  • 当我在等待期间编辑文件时(例如使用 Notepad++ ),编辑器打开文件而没有任何显示内容,我可以编辑并保存,但之后读取返回 -1 并且文件为空

预期行为:

  • 对该文件的任何其他访问都应返回 Windows 错误(文件正在使用中),就像您打开 Word 文档并尝试删除它时一样

我做错了什么?

import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class TestLocking {

    public static void main(String[] args) throws Exception {

        String filename = "testfile.txt";

        Path file = Path.of(filename);
        if (!Files.exists(file)) {
            String content = "foo";
            System.out.format("File '%s' not found - create and fill with '%s'.%n%n", file.toAbsolutePath().toString(),
                    content);
            Files.write(file, content.getBytes(Charset.defaultCharset()));
        }

        FileChannel filechannel = FileChannel.open(file, StandardOpenOption.READ, StandardOpenOption.WRITE);
        FileLock lock = filechannel.tryLock(0, Long.MAX_VALUE, false);

        if (lock == null) {
            System.out.println("File already locked.");
        } else {
            System.out.println("File lock aquired.");
            Thread.sleep(10000);
            System.out.println("reading file..");
            ByteBuffer buffer = ByteBuffer.allocate(1000);
            int readBytes = filechannel.read(buffer);
            System.out.format("read %d bytes.%n", readBytes);
            buffer.flip();
            final byte[] array = new byte[buffer.remaining()];
            buffer.duplicate().get(array);
            String s = new String(array, Charset.defaultCharset());
            System.out.println("---FILE-CONTENT---");
            System.out.println(s);
            System.out.println("---FILE---END-----");
            // unlock
            lock.close();
            System.out.println("File lock released.");
        }
        filechannel.close();
    }
}

edit1:忘记了channel.close()

最佳答案

在 Java 中,可以使用 FileChannel 来获取文件锁,FileChannel 为此提供了两种方法 — lock() 和 tryLock()。

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class FileLockTest {
    private static final Log LOG = LogFactory.getLog(FileLockTest.class);
    private static FileChannel fc;
    private static RandomAccessFile randomAccessFile;
    public FileLockTest(String fileName) throws FileNotFoundException {
        randomAccessFile = new RandomAccessFile(fileName, "rw");
    }
    public void writeToFileWithLock(String data) {
        fc = randomAccessFile.getChannel();
        ByteBuffer buffer = null;
        try (fc; randomAccessFile; FileLock fileLock = fc.tryLock()) {
            if (null != fileLock) {
                buffer = ByteBuffer.wrap(data.getBytes());
                buffer.put(data.toString().getBytes());
                buffer.flip();
                while (buffer.hasRemaining())
                    fc.write(buffer);
            }
        } catch (OverlappingFileLockException | IOException ex) {
            LOG.error("Exception occured while trying to get a lock on File... " + ex.getMessage());
        }
    }
}

关于java - 如何使用 Java (openjdk 11) 在 Windows 10 中独占锁定文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61914309/

相关文章:

windows - expo version 命令显示在这台机器上禁用的运行脚本

java - 如何在 IntelliJ IDEA 和 OpenJDK11 中使用 Jasper Reports

java - Gradle bootrun 因 openjdk 11 失败

Java 剪贴板可用性

仅当从上下文菜单调用时,Python 脚本才会在 subprocess.run() 调用上执行失败

java - java中的内存如何表示null

android - .android\repositories.cfg无法加载

java - 从 1.8 迁移到 openJDK11 时如何解决 "sun.security.x509"不可见问题?

java - 如何访问另一个类中的 JTextField 内容

java - 在链接列表中查找最小值