0

openjdk 11 を使用して Windows 10 でファイルを排他的にロックしようとしていますが、意図したとおりに機能しません。ロックが設定されている限り、自分のプロセス以外はファイルを編集/削除/...できないことを保証する必要があります。

私は答えを探しましたが、それらは a) かなり古く、b) 私と同じコードを使用し、「これがどのように行われたか」と言います。

以下は、テストファイルを作成し、ロックを取得してから 10 秒間待ってから読み取る簡単な例です。非共有ロックにはオープン オプション 'WRITE' が必要です (それ以外の場合、tryLock は UnsupportedOperationException をスローします)。

これまでの動作:

  • 待機中に (Windows エクスプローラーで) ファイルを削除すると、読み取りによってファイルの元のコンテンツが配信されますが、ファイルを削除した瞬間にエクスプローラーの概要からファイルが消えます。
  • 待機中にファイルを編集すると (たとえば、メモ帳 ++ を使用)、エディターはコンテンツを表示せずにファイルを開きます。編集して保存することはできますが、その後、読み取りは -1 で返され、ファイルは空です。

予想される動作:

  • ファイルへのその他のアクセスは、Word 文書を開いて削除しようとした場合のように、Windows エラー (使用中のファイル) を返す必要があります。

私は何を間違っていますか?

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() を忘れた

4

1 に答える 1

0

Java では、この目的のために lock() と tryLock() の 2 つのメソッドを提供する FileChannel を使用してファイル ロックを取得できます。

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());
        }
    }
}
于 2020-05-20T13:46:16.513 に答える