128

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

明確にするために:

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

4

8 に答える 8

119

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

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

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

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

于 2008-09-24T16:20:47.403 に答える
63

パッケージ内のクラスを使用しないでください。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) {
    }
于 2012-01-26T15:20:33.737 に答える
17

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

FileChannel.lock()

于 2008-09-24T16:13:36.577 に答える
8

java.nio.channels.FileLockをjava.nio.channels.FileChannelと組み合わせて使用​​する

于 2008-09-24T16:14:07.467 に答える
5

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

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

于 2008-09-25T03:48:21.743 に答える
3

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

于 2008-09-25T03:40:36.537 に答える
1

winscp または ftp を使用して転送する場合は、UNIX でこれを使用します。

public static void isFileReady(File entry) throws Exception {
        long realFileSize = entry.length();
        long currentFileSize = 0;
        do {
            try (FileInputStream fis = new FileInputStream(entry);) {
                currentFileSize = 0;
                while (fis.available() > 0) {
                    byte[] b = new byte[1024];
                    int nResult = fis.read(b);
                    currentFileSize += nResult;
                    if (nResult == -1)
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("currentFileSize=" + currentFileSize + ", realFileSize=" + realFileSize);
        } while (currentFileSize != realFileSize);
    }
于 2020-08-12T15:44:04.847 に答える