web-dev-qa-db-ja.com

Javaを使用してファイルをロックする方法(可能な場合)

FileReaderを使用してファイルを開くJavaプロセスがあります。別の(Java)プロセスがこのファイルを開かないようにするにはどうすればよいですか、少なくともその2番目のプロセスにファイルが既に開かれていることを通知できますか?これにより、ファイルが開いている場合に2番目のプロセスが自動的に例外を取得します(これにより問題が解決します)か、何らかのフラグまたは引数を使用して最初のプロセスで明示的に開く必要がありますか?

明確にするために:

フォルダーをリストし、リスト内の各ファイルを開いて処理するJavaアプリがあります。各ファイルを順番に処理します。各ファイルの処理には、ファイルの読み取りと内容に基づいた計算が含まれ、約2分かかります。別のJavaアプリもあり、同じことを行いますが、代わりにファイルに書き込みます。私が望むのは、これらのアプリを同時に実行できるようにして、シナリオがこのようになることです。 ReadAppはフォルダーをリストし、ファイルA、B、Cを見つけます。ファイルAを開き、読み取りを開始します。 WriteAppはフォルダーをリストし、ファイルA、B、Cを見つけます。ファイルAを開き、開いていることを(例外または何らかの方法で)確認し、ファイルBに移動します。ReadAppはファイルAを終了し、Bに進みます。は開いており、Cに続きます。ReadAppが同じファイルを読み込んでいる間、またはその逆の場合、WriteAppが書き込みを行わないことが重要です。それらは異なるプロセスです。

111
Paralife

FileChannel.lockはおそらくあなたが望むものです。

FileInputStream in = new FileInputStream(file);
try {
    Java.nio.channels.FileLock lock = in.getChannel().lock();
    try {
        Reader reader = new InputStreamReader(in, charset);
        ...
    } finally {
        lock.release();
    }
} finally {
    in.close();
}

(免責事項:コードはコンパイルされておらず、テストされていません。)

FileLockのAPIドキュメント の「プラットフォーム依存関係」というセクションに注意してください。

109

Java.ioパッケージのクラスを使用しないで、代わりにJava.nioパッケージを使用してください。後者にはFileLockクラスがあります。 FileChannelにロックを適用できます。

 try {
        // Get a file channel for the file
        File file = new File("filename");
        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

        // Use the file channel to create a lock on the file.
        // This method blocks until it can retrieve the lock.
        FileLock lock = channel.lock();

        /*
           use channel.lock OR channel.tryLock();
        */

        // Try acquiring the lock without blocking. This method returns
        // null or throws an exception if the file is already locked.
        try {
            lock = channel.tryLock();
        } catch (OverlappingFileLockException e) {
            // File is already locked in this thread or virtual machine
        }

        // Release the lock - if it is not null!
        if( lock != null ) {
            lock.release();
        }

        // Close the file
        channel.close();
    } catch (Exception e) {
    }
56
ayengin

Java NIOJDK 1.4以上)を使用できる場合は、探していると思いますJava.nio.channels.FileChannel.lock()

FileChannel.lock()

16
KC Baltz

Java.nio.channels.FileLockJava.nio.channels.FileChannel と組み合わせて使用​​する

6
Matt

これはあなたが探しているものではないかもしれませんが、別の角度から問題に直面するために....

これら2つのJavaプロセスは、同じアプリケーション内の同じファイルにアクセスする可能性がありますか?おそらく、単一の同期メソッドを介してファイルへのすべてのアクセスをフィルタリングすることができます(または、さらに良いのは JSR-166 )。これにより、ファイルへのアクセスを制御でき、アクセス要求をキューに入れることもできます。

5
pkaeding

RandomAccessFileを使用してチャネルを取得し、lock()を呼び出します。入力または出力ストリームによって提供されるチャネルには、適切にロックするための十分な特権がありません。 finallyブロックで必ずunlock()を呼び出してください(ファイルを閉じてもロックが解除されるとは限りません)。

3
Kevin Day

MacOS/Windows上の複数のユーザーが複数のファイルの同じデータを共有する必要があるアプリケーションを作成したときに、数年前に同じ問題が見つかりました。ファイルのロックはMacOSでは機能しなかったため、独自の「ioFile」クラスを作成しました。このクラスは、ファイルアクセスの独自のレジスタ(オープンr/o、オープンr/wなど)、およびロックの「所有者」を維持しますこれは、異なるOSを使用する異なるマシン上の異なるユーザーからのアクセスを制御できる唯一の方法です。

0
user3654656

以下は、プロセスがJVMによって実行されるまでファイルをロックするためのサンプルスニペットコードです。

 public static void main(String[] args) throws InterruptedException {
    File file = new File(FILE_FULL_PATH_NAME);
    RandomAccessFile in = null;
    try {
        in = new RandomAccessFile(file, "rw");
        FileLock lock = in.getChannel().lock();
        try {

            while (in.read() != -1) {
                System.out.println(in.readLine());
            }
        } finally {
            lock.release();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
0
Ajay Kumar