1

Java SE 7 で利用可能な WatchService を使用して (ネットワーク マシン上の) リモート ディレクトリを監視しようとしています。Windows XP でプログラムを実行すると問題なく動作しますが、Windows 7 では WatchService.take() が待機しません。無効なキーを返します。

サンプルコードは次のとおりです。

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.WatchEvent.Kind;

public class MyWatchingService {

public void watchDir(Path path) throws IOException, InterruptedException {

    try (WatchService watchService = FileSystems.getDefault().newWatchService()) {

        path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE);        

        while (true) {
            // gets a watch key
            final WatchKey key = watchService.take();

            // retrieves pending events for a key.
            for (WatchEvent<?> watchEvent : key.pollEvents()) {

                // retrieves the event type and count.
                // gets the kind of event (create, delete) 
                final Kind<?> kind = watchEvent.kind();

                // handles OVERFLOW event
                if (kind == StandardWatchEventKinds.OVERFLOW) {
                    continue;
                } 

                final WatchEvent<Path> watchEventPath = cast(watchEvent);
                final Path entry = watchEventPath.context();

                // outputs an event type and entry
                System.out.println(kind + " -> " + entry);
            }

            boolean valid = key.reset();

            //exit loop if the key is not valid
            if (!valid) {
                System.out.println("Key is invalid!");
                break;
            }
        }

    }
}

public void writeFile (Path path, String fileName) throws IOException {
    Path target = Paths.get(path.toString(), fileName);
    if (target.toFile().exists()) {
        Files.delete(target);
        System.out.println("file is deleted ok!");
    }
    Path fileTo = Files.createFile(target);
    Files.write(fileTo, String.valueOf(true).getBytes(), StandardOpenOption.WRITE);
    System.out.println("file is written ok!");
}

@SuppressWarnings("unchecked")
private static <T> WatchEvent<T> cast(WatchEvent<?> event) {
    return (WatchEvent<T>)event;
}

/**
 * @param args
 */
public static void main(String[] args) {

    // case 1: network directory mapped to Y volume
    final Path path = Paths.get("Y:/workspace");
    // case 2: local directory: 
//  final Path path = Paths.get("D:/workspace");

    MyWatchingService service = new MyWatchingService();
    try {
        long start = System.currentTimeMillis();
        service.watchDir(path);
        System.out.println("exiting after " + Long.toString(System.currentTimeMillis() - start) + "ms...");
        service.writeFile(path, "test");
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

出力は次のとおりです。

Key is invalid!
exiting after 16ms...
file is deleted ok!
file is written ok!

ご覧のとおり、このネットワーク ディレクトリにファイルを書き込み/削除できるかどうかを確認しました。私はまた、このようなパスを定義するマッピングなしで試しました://server/workspace運もありません. ローカル ディレクトリを使用してコメント アウトされたケース 2 に対して同じプログラムを実行すると、予想どおり出力がなく待機状態になります。

jdk1.7.0_17、64ビットを使用しています。(私はjre7、32ビットを試しましたが、運もありません). リモート ディレクトリは、Windows Server 2008 R2 Standard にあります。

APIで次の文を読みましたが、まったく不可能であると疑われます。

監視対象のファイルがローカル ストレージ デバイスにない場合、ファイルへの変更を検出できるかどうかは実装によって異なります。特に、リモート システムで実行されたファイルへの変更を検出する必要はありません。

私は WatchService を使用してこの戦略に多くの時間を費やしてきたので、これは私にとって悪い知らせです。Windows 7で動作しない理由や経験がある人はいますか、それともまったく可能ですか? そうでない場合、代替アプローチは何でしょうか。

4

1 に答える 1

2

ドキュメントが言うように:「監視」がネットワークドライブでまったく機能するとは思わないでしょう。

それが機能するかどうかは、クライアントの OS とその構成サーバーの OS とその構成、およびその他の未知の要因に依存します。非常に壊れやすく、当てにする価値がないようです。

docsにも簡単な代替案が記載されています。

[...] または、ネイティブ機能が利用できない場合に、ポーリングなどの基本的なメカニズムを使用する

ポーリング アプローチは、まったく使用せずに純粋な Java で実装できますNIO。警告: リソース (ネットワーク) の使用率が高くなる可能性があります。

そして、いつものように、少し戻って、これらのファイル システム操作に基づいて「ネットワーク プロトコル」を構築する必要があるかどうか、または別の方法で必要/必要なものを達成できるかどうかを再検討することをお勧めします。

于 2013-03-28T18:08:41.453 に答える