単純にファイル生成されたかどうかを監視するのであれば FileSystemWathcer
を利用するとよいと思います。
ちまたのコードでもそのようなものが多いハズです。
ただ… FileSystemWatcher だけだと、ファイル生成された瞬間にイベントが発生するため、大きなファイルを生成中だとファイルオープンできない問題があります。
なので、ファイル生成された後、開けるようになったらイベント発生させるように少し拡張した 「ファイル生成の監視クラス」 を作ってみました。
…と言っても、イベント発生時に生成されたファイルを開けるかどうかチェックして、無理であれば Timer
でもう一度チェックする、といった単純なものです。
目次
仕様
単純には以下のような仕様のものを作ります。
- 監視するディレクトリが指定できる
- 監視するディレクトリはサブディレクトリも監視対象にするかどうか指定できる
- 監視するファイルのフィルタ条件を指定できる
- ファイル生成されて開けるようになったとき Fireイベント が発生する
ただ、実装上の問題から、 Fireイベント は別スレッドで実行される場合がある、といった注意点があります。
ファイル生成を監視するクラス の サンプルコード
ファイル生成を監視するクラス本体 "FileCreationTrigger
"と、イベント発生時に受け渡されるイベント変数 "FileCreationEventArgs
" のサンプルコードを以下に掲載します。
FileCreationTrigger.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | namespace garafu { using System; using System.Collections.Generic; using System.IO; using System.Timers; /// <summary> /// ファイル生成を監視 /// </summary> public class FileCreationTrigger : IDisposable { #region ' フィールド // --------------------------------------- // フィールド // --------------------------------------- /// <summary> /// 監視する対象のフィルタ条件 /// </summary> private string filter = string .Empty; /// <summary> /// サブディレクトリを検索するかどうか /// </summary> private bool includeSubdirectories = true ; /// <summary> /// 監視する間隔 /// </summary> private double interval = 0; /// <summary> /// 監視する対象のフォルダパス /// </summary> private string path = string .Empty; /// <summary> /// Timerクラスのインスタンス /// </summary> private Timer timer; /// <summary> /// FileSystemWatcherクラスのインスタンス /// </summary> private FileSystemWatcher watcher; /// <summary> /// 生成されたファイルでまだイベントを発生させていないファイルのリスト /// </summary> private List< string > watches = new List< string >(); #endregion #region ' コンストラクタ // --------------------------------------- // フィールド // --------------------------------------- /// <summary> /// FileCreationTrigger クラスのインスタンスを生成、初期化します。 /// </summary> public FileCreationTrigger() { this .InitializeInstance( null , null , null , null ); } /// <summary> /// 監視ディレクトリ、監視ファイルのフィルタ条件、サブディレクトリを監視するかどうか を指定して /// FileCreationTrigger クラスのインスタンスを生成、初期化します。 /// </summary> /// <param name="path">監視ディレクトリ</param> /// <param name="fileter">監視ファイルのフィルタ条件</param> /// <param name="includeSubdirectories">サブディレクトリを監視するかどうか</param> public FileCreationTrigger( string path, string fileter, bool includeSubdirectories) { this .InitializeInstance(path, fileter, includeSubdirectories, null ); } #endregion #region ' イベント // --------------------------------------- // イベント // --------------------------------------- /// <summary> /// 監視対象ディレクトリに指定されたフィルタに該当するファイルが生成されたとき発生します。 /// メインスレッドとは別スレッドで動作する場合があります。 /// </summary> public event EventHandler<FileCreationEventArgs> Fire; #endregion #region ' プロパティ // --------------------------------------- // プロパティ // --------------------------------------- /// <summary> /// 監視対象ファイルのフィルタ条件を取得または設定します。 /// </summary> public string Filter { get { return this .filter; } set { this .filter = value; this .watcher.Filter = value; } } /// <summary> /// サブディレクトリを監視するかどうかを取得または設定します。 /// </summary> public bool IncludeSubdirectories { get { return this .includeSubdirectories; } set { this .includeSubdirectories = value; this .watcher.IncludeSubdirectories = value; } } /// <summary> /// 監視間隔(msec)を取得または設定します。 /// </summary> public double Interval { get { return this .interval; } set { this .interval = value; this .timer.Interval = value; } } /// <summary> /// 監視対象ディレクトリのパスを取得または設定します。 /// </summary> public string Path { get { return this .path; } set { this .path = value; this .watcher.Path = value; } } #endregion #region ' メソッド // --------------------------------------- // メソッド // --------------------------------------- /// <summary> /// インスタンスを廃棄します。 /// </summary> public void Dispose() { this .watcher.Dispose(); this .timer.Dispose(); } /// <summary> /// Fireイベントの発生を開始します。 /// </summary> public void Start() { this .watcher.EnableRaisingEvents = true ; this .timer.Start(); } /// <summary> /// Fireイベントの発生を停止します。 /// </summary> public void Stop() { this .watcher.EnableRaisingEvents = false ; this .timer.Stop(); } /// <summary> /// FileSystemWatcherでCreatedイベントが発生したとき実行されます。 /// </summary> /// <param name="sender">呼び出し元インスタンス</param> /// <param name="e">イベント引数</param> private void FileSystemWatcher_Created( object sender, FileSystemEventArgs e) { if ( this .IsFileLocked(e.FullPath) == false ) { if ( this .watches.Contains(e.FullPath)) { this .watches.Remove(e.FullPath); } this .OnFire(e.FullPath); } else { if ( this .watches.Contains(e.FullPath) == false ) { this .watches.Add(e.FullPath); } } } /// <summary> /// インスタンスを初期化します。 /// </summary> /// <param name="path">監視ディレクトリのパス。デフォルトはカレントディレクトリ。</param> /// <param name="filter">監視する対象のフィルタ条件。デフォルトはすべてのファイル「*」。</param> /// <param name="includeSubdirectories">サブディレクトリを検索するかどうかデフォルトは true。</param> /// <param name="interval">監視する間隔(msec)。デフォルトは 1000 ミリ秒。</param> private void InitializeInstance( string path, string filter, bool ? includeSubdirectories, double ? interval) { // インスタンス生成 this .watcher = new FileSystemWatcher(); this .timer = new Timer(); // 初期設定 this .Path = string .IsNullOrEmpty(path) ? Environment.CurrentDirectory : path; this .Filter = string .IsNullOrEmpty(filter) ? "*" : filter; this .IncludeSubdirectories = includeSubdirectories.GetValueOrDefault( true ); this .Interval = interval.GetValueOrDefault(1000); // イベントのアタッチ this .watcher.Created += new FileSystemEventHandler( this .FileSystemWatcher_Created); this .timer.Elapsed += new ElapsedEventHandler( this .Timer_Elapsed); } /// <summary> /// 指定されたファイルがロックされているかどうかを返します。 /// </summary> /// <param name="path">検証したいファイルへのフルパス</param> /// <returns>ロックされているかどうか</returns> private bool IsFileLocked( string path) { FileStream stream = null ; try { stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None); } catch { return true ; } finally { if (stream != null ) { stream.Close(); } } return false ; } /// <summary> /// Fireイベントを発生させます。 /// </summary> /// <param name="fullpath">イベント発生源となったファイルへのフルパス</param> private void OnFire( string fullpath) { if ( this .Fire != null ) { this .Fire( this , new FileCreationEventArgs(fullpath)); } } /// <summary> /// TimerでElapsedイベントが発生したとき実行されます。 /// </summary> /// <param name="sender">呼び出し元インスタンス</param> /// <param name="e">イベント引数</param> private void Timer_Elapsed( object sender, ElapsedEventArgs e) { foreach (var fullpath in this .watches) { if ( this .IsFileLocked(fullpath) == false ) { this .watches.Remove(fullpath); this .OnFire(fullpath); } } } #endregion } } |
FileCreationEventArgs.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | namespace garafu { using System; /// <summary> /// ファイル生成 /// </summary> public class FileCreationEventArgs : EventArgs { /// <summary> /// 生成されたファイルへのフルパスを取得します。 /// </summary> public string FullPath { get ; private set ; } /// <summary> /// パス情報を指定して、FileCreationEventArgs クラスのインスタンスを生成、初期化します。 /// </summary> /// <param name="fullpath">パス情報</param> public FileCreationEventArgs( string fullpath) { this .FullPath = fullpath; } } } |
ファイル生成を監視するクラス の 利用例
ファイル生成を監視するクラスの利用方法は、インスタンス生成して Fireイベント に イベントハンドラ を接続し、 Startメソッド を呼び出すだけです。 以下にサンプルコードを掲載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | namespace WpfApplication1 { using System; using System.IO; using System.Windows; using garafu; /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { private FileCreationTrigger trigger; public MainWindow() { this .InitializeComponent(); this .trigger = new FileCreationTrigger(); this .trigger.Fire += new EventHandler<FileCreationEventArgs>( this .Trigger_Fire); this .trigger.Start(); } private void Trigger_Fire( object sender, FileCreationEventArgs e) { // ファイル生成されたときの処理 } } } |
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!