8

非常に小さなファイルをコピーして、監視サービスによって監視されるフォルダーに貼り付けようとしました。初めてはうまくいきますが、その後のすべてのコピー&ペースト操作で、別のプロセスがすでにファイルを処理しているという例外が発生します。実験の結果、コンテンツがコピーされたときではなく、Windows がファイルを作成したときにサービスに通知されることがわかりました。ファイルをロックすると、Windows はデータをコピーできず、ファイルは空になります。一方、ファイルをディレクトリに移動すると、すべて正常に動作します。

それはWindowsのバグですか?Mac または Linux ワークステーションではテストできませんでした。あるいは、私が無能だっただけかもしれません。どんな助けでも大歓迎です。

私のコードは次のようになります。

try (WatchService watchService = importPath.getFileSystem().newWatchService()) {
  importPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
  handleExistingFiles();

  try {
    do {
      WatchKey watchKey = watchService.take();
      if (!watchKey.isValid()) {
        continue;
      }

      boolean hasCreationEvents = false;
      for (WatchEvent<?> event : watchKey.pollEvents()) {
        hasCreationEvents |= event.kind().equals(StandardWatchEventKinds.ENTRY_CREATE);
      }
      watchKey.reset();

      if (hasCreationEvents) {
        handleNewFiles();
      }
    }
    while (!Thread.currentThread().isInterrupted());
  }
  catch (InterruptedException ignoredEx) {
    Thread.currentThread().interrupt();
  }
}
4

1 に答える 1

10

コピー操作は常にアトミックであるとは限りません。

アトミック コピー (または移動) を使用すると、単一の ENTRY_CREATE イベントを取得し、イベントによって参照されるファイルが完成し、読み取り可能になります。

コピーがアトミックでない場合、ファイルの作成時に ENTRY_CREATE イベントを受け取り、コピー操作によってファイルが書き込まれている間に 1 つ以上の ENTRY_MODIFY イベントを受け取ります。

コピー操作がいつファイルへの書き込みを終了して解放したかを判断する簡単な方法はありません。OS やファイル システムによっては、コピー操作によってロックされているファイルを読み取り用に開こうとすると FileNotFoundException が発生したり、ファイルを正常に開いても実際に読み取ったときに部分的な内容が取得されたりすることがあります。

ENTRY_CREATE の直後にファイルの読み取りを試行し、最初の読み取りが失敗した場合は後で読み取りを再スケジュールするなど、いくつかのヒューリスティックを実装する必要があります。

于 2014-04-09T08:12:11.823 に答える