4

私は Apache Commons IO を使用しています:

     FileUtils.copyFileToDirectory(srcFile, destDir)

コピー中に Windows で宛先ファイルをロックするにはどうすればよいですか? 次を使用すると、Windowsはファイルを正しくロックします。

      Runtime.getRuntime().exec(
      "cmd /c copy /Y \"" + srcFile.getCanonicalPath() + "\" \""
          + destDir.getCanonicalPath() + "\"").waitFor();

注: 競合はローカル プログラムではなく、外部プログラムです。ファイルはリモート システムにコピーされています。リモート システムは、コピーを完了する前にファイルを処理しています。システムは Windows であるため、通常のコピーではファイルがロックされ、外部プログラムからのアクセスがブロックされます。

4

3 に答える 3

6

java.nio.channels.FileChannelを使用すると、基礎となるファイル システムに固有のメソッドを使用して、ファイルのFileLockを取得できます(そのような機能がサポートされている場合)。

このロックは、Java 以外のプロセスであっても、マシン上のプロセス全体で機能します。(実際、ロックは特定の JVM インスタンスに代わって保持されるため、プロセス内の複数のスレッド間、または同じ JVM 内の複数のプロセス間の競合の管理には適していません)。

ここには多くの注意事項がありますが、Windows で作業している場合は調査する価値があります。

javadoc から:

このファイル ロック API は、基盤となるオペレーティング システムのネイティブ ロック機能に直接マップすることを目的としています。したがって、ファイルに保持されているロックは、プログラムが記述されている言語に関係なく、ファイルにアクセスできるすべてのプログラムから見える必要があります。

ロックによって別のプログラムがロックされた領域のコンテンツにアクセスするのを実際に防止するかどうかは、システムに依存するため未指定です。一部のシステムのネイティブ ファイル ロック機能は単なる助言にすぎません。つまり、プログラムは、データの整合性を保証するために、既知のロック プロトコルを協力して監視する必要があります。他のシステムでは、ネイティブ ファイル ロックが必須です。つまり、あるプログラムがファイルの領域をロックすると、他のプログラムはロックに違反するような方法でその領域にアクセスできなくなります。さらに他のシステムでは、ネイティブ ファイル ロックが推奨か強制かをファイルごとに設定できます。プラットフォーム間で一貫した正しい動作を確保するために、この API によって提供されるロックをアドバイザリ ロックのように使用することを強くお勧めします。

一部のシステムでは、ファイルの領域で強制ロックを取得すると、その領域がメモリにマップされなくなり、その逆も同様です。ロックとマッピングを組み合わせるプログラムは、この組み合わせが失敗しないように準備する必要があります。

一部のシステムでは、チャネルを閉じると、そのチャネルを介してロックが取得されたか、同じファイルで開かれている別のチャネルを介してロックが取得されたかに関係なく、Java 仮想マシンが保持している基になるファイルのすべてのロックが解放されます。プログラム内で、特定のファイルのすべてのロックを取得するために一意のチャネルを使用することを強くお勧めします。

一部のネットワーク ファイル システムでは、ロックされた領域がページで整列され、基盤となるハードウェアのページ サイズの整数倍である場合にのみ、メモリ マップト ファイルでファイル ロックを使用できます。一部のネットワーク ファイル システムは、特定の位置 (多くの場合 230 または 231) を超える領域にファイル ロックを実装していません。一般に、ネットワーク ファイルシステムに存在するファイルをロックするときは細心の注意を払う必要があります。

于 2009-02-02T16:05:16.450 に答える
4

Javaはファイルロックをネイティブにサポートしていません。

ファイルの競合がプログラム内から発生している場合は、ファイルコピーの上に追加の同期を構築して、同時書き込みが相互に干渉しないようにする必要があります。ただし、競合がソフトウェアの外部から発生している場合は、できることはあまりありません。名前の変更は多かれ少なかれアトミックであるため(ファイルシステムによって異なります)、ファイルを一時ディレクトリに書き込んでから名前を変更してみてください。

そもそもなぜファイルをロックする必要があるのか​​について、より多くの情報を得るのに役立ちます。

競合はローカルプログラムではなく、外部プログラムとの競合です。ファイルはリモートシステムにコピーされています。リモートシステムは、コピーが完了する前にファイルを処理しています。システムはWindowsであるため、通常のコピーはファイルをロックし、外部プログラムへのアクセスをブロックします。

その場合は、一時ファイルに書き込んでから、ファイルが完全にコピーされたときに名前を変更してみてください。ファイルの名前変更は(ネットワーク化されていないファイルシステムでの)不可分操作であるため、機能するはずです。

于 2009-01-23T16:17:40.843 に答える
1

ファイルをコピーするときは、常に一時的なファイル名にコピーし、書き込みが完了したらファイルの名前を変更してください。このようにして、別のプロセスが破損したファイルを見ることはありません。

さらに良いことに、*.tmp に書き込むことができます。次に、宛先ファイルが存在するかどうかを確認します。dest ファイルが存在する場合は、名前を *.bak に変更します。最後に *.tmp -> dest の名前を変更します。

于 2009-01-23T16:26:24.710 に答える