質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

5712閲覧

java 監視サービス 複数フォルダ監視時の疑問

panda_jp

総合スコア25

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

1クリップ

投稿2016/06/28 02:40

いつも参考にさせていただいています。

JavaのWatchServiceを用いてフォルダの監視を行おうとしています。
色々なサンプルを参考にしていますが、下記の内容が少し理解できなかったため、
質問させてください。

java

1File watchDirFile = new File("watchDir"); 2Path watchDirPath = watchDirFile.toPath(); 3WatchKey watchKey = watchDirPath.register(watchService, 4 StandardWatchEventKind.ENTRY_CREATE, StandardWatchEventKind.ENTRY_MODIFY); 5

Path を作成して register() を呼び出せば、同じ 1 つの WatchService インスタンスで複数のディレクトリーを監視することもできます。

とあったのですが、例えば
①C:\temp
②C:\temp\sub1
③C:\temp\sub2
④D:\aaaa
⑤G:\bbbb
みたいに、監視するドライブの階層が違っても「Path を作成して register() を呼び出せば」同じWatchService を使用できるという認識でいいのでしょうか?

ご教授お願いいたします。

java 1.8

A-pZ👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ご推察のとおり、1つのWatchServiceに複数のPathを登録することで、複数のディレクトリが監視対象に入ります。1つのディレクトリ監視は、その指定したディレクトリのみ監視しますので、階層が異なるディレクトリがある場合は、その階層以下にあるディレクトリを登録しなければなりません。

java

1package sample; 2 3import java.io.File; 4import java.io.IOException; 5import java.nio.file.FileSystem; 6import java.nio.file.FileSystems; 7import java.nio.file.Path; 8import java.nio.file.StandardWatchEventKinds; 9import java.nio.file.WatchEvent; 10import java.nio.file.WatchKey; 11import java.nio.file.WatchService; 12import java.util.ArrayList; 13import java.util.Arrays; 14import java.util.List; 15 16/** 17 * @author A-pZ 18 */ 19public class Watcher { 20 21 private static final List<String> watchDir = Arrays.asList("D:\\app\\work\\watchDir","D:\\app\\work\\watchDir\\sub","D:\\app\\work\\watchDir\\ex"); 22 23 private static volatile boolean stop = false; 24 25 public static void main(String[] args) throws IOException, InterruptedException { 26 FileSystem fileSystem = FileSystems.getDefault(); 27 WatchService watchService = fileSystem.newWatchService(); 28 29 List<WatchKey> watchKeys = new ArrayList<>(); 30 watchDir.stream().forEach(dir -> { 31 Path watchDirPath = new File(dir).toPath(); 32 WatchKey watchKey; 33 try { 34 watchKey = watchDirPath.register(watchService, 35 StandardWatchEventKinds.ENTRY_CREATE, 36 StandardWatchEventKinds.ENTRY_MODIFY, 37 StandardWatchEventKinds.ENTRY_DELETE 38 ); 39 watchKeys.add(watchKey); 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 44 }); 45 46 Runtime.getRuntime().addShutdownHook(new Thread() { 47 @Override 48 public void run() { 49 stop = false; 50 } 51 }); 52 53 while (!Thread.currentThread().isInterrupted() && !stop) { 54 System.out.println("Watching..."); 55 56 WatchKey take = watchService.take(); 57 System.out.println("watch name:" + take.watchable().toString()); 58 59 if ( take.isValid()) { 60 List<WatchEvent<?>> events = take.pollEvents(); 61 62 // 検出したイベンドがListで返されるので内容を解析 63 events.stream().forEach(ev -> { 64 System.out.println("イベント:" + ev.kind()); 65 System.out.println("ファイル:" + ev.context()); 66 System.out.println("回数 :" + ev.count()); 67 }); 68 69 // イベントを送出し終わった後はリセットして監視再開 70 take.reset(); 71 } 72 } 73 74 System.out.println("close."); 75 watchKeys.stream().forEach(dir -> { 76 dir.cancel(); 77 }); 78 } 79 80}

参考サイト:Yosuke’s Blog|WatchServiceを利用したIOイベントハンドリング

投稿2016/06/28 04:22

A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/28 14:30 編集

A-pZさん、javadocにはイベント発生は実装依存と書かれています。 実際、こちらのWindowsマシンでは、サブディレクトリのファイルが更新されると、親ディレクトリでもイベントが発生しました。 また、本題からずれますが、 mainメソッドがInterruptedExceptionをスローしちゃっているので、正しい終了処理ができない場合があります。 強制終了させられた時にクリーンアップを行いたい場合は、mainスレッドではなく、シャットダウン・フックのスレッドで終了処理を行ったほうが良いですね。
A-pZ

2016/06/28 15:38

sipadan2003様、補足ありがとうございます。 はい、最初に読み込んだディレクトリ内にサブディレクトリが含まれていた場合は、もしサブディレクトリにファイルを置いた、などは、"サブディレクトリそのものに変更があった通知まで"しか受け取れず、ファイルが新しく作られたかどうかまでは検出できないのです。 あと、InterruptExceptionについては、確かにそうですねd(・ω・) ナイス指摘です!
panda_jp

2016/06/28 19:31

A-pZ様 回答ありがとうございます。 監視対象のフォルダをリスト化して複数のPathを登録してあげれば良かったのですね。 色々参考になりました。 落ち着いたらもっとjavaの勉強をします。
panda_jp

2016/06/30 08:05

一度解決済みにしたのですが、どうしても分からないことがあり、再度質問させていただきました。 質問の内容がタイトルと異なりますが、どなたかご教授ください。 A-pZ様のソースを実行し確認したのですが、確かに複数フォルダの監視ができたのですが、一度のフォルダ監視で「イベント:」「ファイル:」「回数」がそれぞれ2度出力されます。 一度目はテキストの「.text」が取得できない形(以下System.out)です。 ----------------------- Watching... watch name:C:\aaa イベント:ENTRY_CREATE ファイル:kaikuvds 回数 :1 イベント:ENTRY_CREATE ファイル:kaikuvds.txt 回数 :1 --------------------------------- List<WatchEvent<?>> events = take.pollEvents(); でeventsのlistsizeが2になっているのがキーなのでしょうが、これを一度目で下記のように出力するにはどうすれば良いのでしょうか? 色々調べてみたのですが、どうしても原因と解決方法がわかりません。 ----------------------- Watching... watch name:C:\aaa イベント:ENTRY_CREATE ファイル:kaikuvds.txt 回数 :1 --------------------------------- ここのコメント欄の書き方が不適切な場合は指摘してください。 どうぞよろしくお願いいたします。
A-pZ

2016/06/30 08:25

操作した内容がないとさすがに答えにくいです(´・ω・`) kaikuvds(拡張子なし) はフォルダを作成したのでしょうか?
panda_jp

2016/06/30 14:10

A-pz様 そうですよね・・・大変失礼いたしました。 操作手順は以下です。 -------------------------------------------- ①C:\\temp, C:\\aaa, C:\\aaa\bbbを監視フォルダとしてセット ②監視イベントは新規イベントのみ(StandardWatchEventKinds.ENTRY_CREATEのみ)で設定 ③監視システム実行後、C:\aaaにkaikuvds.txtを新規作成(テキストの内容は適当) といった手順です。 上手く伝わりましたでしょうか・・・? 何度も申し訳ありません。 よろしくお願いいたします。
退会済みユーザー

退会済みユーザー

2016/06/30 17:13 編集

私のWindowsマシンで、同じように実行しました。 1) C:\aaa、C:\aaa\bbbを用意し、両方をENTRY_CREATEのみで監視 2) C:\aaa\kaikuvds.txt を新規作成 秀丸エディタで保存した場合:ENTRY_CREATEイベントが1個発生 メモ帳で保存した場合:ENTRY_CREATEイベントが2個発生 また、最初に拡張子なしのファイルを作成し、拡張子付きのファイル名に変更するという流れで操作すると、貴殿と同様に次のイベントが発生します(回数は無視)。 Watching... watch name:C:\aaa ENTRY_CREATE: aaa watch name:C:\aaa ENTRY_CREATE: aaa.txt 次に、ENTRY_CREATEだけでなくENTRY_DELETEも監視すると、イベント次の流れになりました(回数は無視)。 Watching... watch name:C:\aaa ENTRY_CREATE: aaa watch name:C:\aaa ENTRY_DELETE: aaa ENTRY_CREATE: aaa.txt つまり、ツールによってファイル作成方法が異なる可能性があることを示唆していますね。
panda_jp

2016/07/01 17:10

sipadan2003様 回答ありがとうございます。 ツールとは考えもしなかったです!! どこかで余分にイベントをキャッチしているのかと大分悩みました・・・
guest

0

監視するドライブの階層が違っても「Path を作成して register() を呼び出せば」同じWatchService を使用できるという認識でいいのでしょうか?

javadocの説明によれば、その認識で正しいと考えます。
言い換えると、「1つのWatchServiceで、複数個のディレクトリを監視可能」ということになりますね。

投稿2016/06/28 14:52

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

panda_jp

2016/06/28 19:37

sipadan2003様 回答ありがとうございます。 色々サンプルを見て、メイン・サブディレクトリの複数監視が可能であることは分かったのですが、階層が違う場合の監視方法が分からず困っていました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問