简体   繁体   English

如何使用 Java(openjdk 11)专门锁定 Windows 10 中的文件?

[英]How can i exclusively lock files in Windows 10 with Java (openjdk 11)?

I am trying to exclusively lock a file in Windows 10 with openjdk 11 but it does not work as intended.我正在尝试使用 openjdk 11 专门锁定 Windows 10 中的文件,但它不能按预期工作。 It should guarantee that as long as the lock is in place, no process but my own should be able to edit/delete/... the file.它应该保证只要锁定到位,除了我自己的进程之外,没有进程应该能够编辑/删除/...文件。

I searched for answers, but they are a) quite old and b) use the same code i do and say 'this it how it's done'.我搜索了答案,但它们 a) 很老,b) 使用与我相同的代码并说“这就是它的完成方式”。

Below is a simple example which creates a testfile and waits for 10 seconds after aquiring a lock on it before reading.下面是一个简单的示例,它创建一个测试文件,并在获取锁后等待 10 秒,然后再读取。 The open option 'WRITE' is needed for a non-sharing lock (otherwise tryLock throws an UnsupportedOperationException).非共享锁需要打开选项“WRITE”(否则 tryLock 会引发 UnsupportedOperationException)。

The behaviour so far:到目前为止的行为:

  • when I delete the file (in Windows Explorer) during the wait, the read still delivers the original content of the file but the file is gone from the explorer overview the moment i delete it当我在等待期间删除文件(在 Windows 资源管理器中)时,读取仍然提供文件的原始内容,但文件在我删除它的那一刻从资源管理器概述中消失了
  • when i edit the file during the wait (eg with notepad++), the editor opens the file without any shown content, i can edit and save but afterwards the read returns with -1 and the file is empty当我在等待期间编辑文件时(例如使用记事本++),编辑器打开文件时没有任何显示的内容,我可以编辑并保存,但之后读取返回 -1 并且文件为空

The expected behaviour:预期的行为:

  • any other access to the file should return a windows error (file in use) like when you have a word document open and try to delete it对文件的任何其他访问都应返回 windows 错误(文件正在使用),例如当您打开 Word 文档并尝试将其删除时

What am i doing wrong?我究竟做错了什么?

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: forgot the channel.close() edit1:忘记了 channel.close()

In Java, a file lock can be obtained using FileChannel, which provides two methods — lock() and tryLock() — for this purpose.在 Java 中,可以使用 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());
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM