25

現在、ルーチンの1つでソースディレクトリからファイルを処理するプロジェクトに取り組んでいます。指定されたディレクトリを探し、ファイルが存在する場合はファイルの読み取りと処理を試みるJavaプロセスがあります。ファイルは大きく終了し、他のサードパーティプロセスによって更新されます。問題は、ファイルが完全に書き込まれているかどうかをどのように確認できるかということです。使用しようとしてfile.length()いますが、書き込み処理が完了していなくても実際のサイズが返ってくるようです。ソリューションはプラットフォームに依存する必要があると感じています。どんな助けでもいただければ幸いです。

更新:この質問は重複と実際には違いはありませんが、評価の高い実用的なコードスニペットで答えがあります。

4

6 に答える 6

22

私は解決策を機能させました:

private boolean isCompletelyWritten(File file) {
    RandomAccessFile stream = null;
    try {
        stream = new RandomAccessFile(file, "rw");
        return true;
    } catch (Exception e) {
        log.info("Skipping file " + file.getName() + " for this iteration due it's not completely written");
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                log.error("Exception during closing file " + file.getName());
            }
        }
    }
    return false;
}

@cklabと@Will、そして「排他的ロック」の方法で見ることを提案してくれた他のすべての人に感謝します。他の興味のある人に使ってもらうために、ここにコードを投稿しました。@tigranによって提案された名前変更のソリューションも機能すると思いますが、純粋なJavaソリューションの方が適しています。

PS最初はFileOutputStream代わりに使用しましRandomAccessFileたが、書き込まれているファイルをロックします。

于 2012-06-28T10:27:46.840 に答える
11

プロデューサープロセスは、書き込みが終了したときにファイルを閉じますか?その場合、プロデューサープロセスがまだ生成している場合、排他ロックを使用してコンシューマープロセスでファイルを開こうとすると失敗します。

于 2012-06-28T07:02:35.400 に答える
5

Windowsでこのシナリオに対して過去に使用した簡単な解決策の1つはboolean File.renameTo(File) 、元のファイルを使用して別のステージングフォルダーに移動しようとすることです。

boolean success = potentiallyIncompleteFile.renameTo(stagingAreaFile);

の場合、successはまだ書き込まれています。falsepotentiallyIncompleteFile

于 2013-07-11T21:12:49.927 に答える
3

そのための一般的な解決策はないと思います。一部のアプリケーションは書き込み呼び出しの前にファイルサイズを設定できるため、ファイルサイズを探すのは間違っています。可能性の1つは、ロックを使用することです。これには、ライターが書き込みロック(または排他ロック)を取得する必要があります。ライターを変更できない場合は、Linuxのfuserなど、OSが提供するツールを使用して、ファイルにアクセスするプロセスがあるかどうかを確認できます。

于 2012-06-28T07:06:27.407 に答える
2

このコードを単一のプラットフォームで使用する場合は、 NIOのFileLock機能を使用できる可能性があります。ただし、ドキュメントを注意深く読み、多くのプラットフォームでは、ロックは単なる助言であることに注意してください。

もう1つの方法は、1つのプロセスに、プロセスが認識できない名前でファイルを書き込み、書き込みが完了したときにファイルの名前を認識可能な名前に変更することです。ほとんどのプラットフォームでは、ソースと宛先が同じファイルシステムボリュームである場合、名前変更操作はアトミックです。

于 2012-06-28T07:10:48.857 に答える
1

Java 1.7を使用できる場合は、NIOツール、特にjava.nio.channels.FileChannelを確認してください。

これは、ファイルをロックして読み取る例です。

于 2013-06-05T16:24:38.230 に答える