|
.NET TIPS
監視により作成/変更が通知されたファイルを開くには?
デジタルアドバンテージ 遠藤 孝信
2005/04/01 |
|
|
「TIPS:ファイルやディレクトリの作成/変更/削除を監視するには?」で解説したFileSystemWatcherクラス(System.IO名前空間)を利用するとファイルの作成や変更を即座に知ることができる。しかし、その通知を受けてファイルを加工したり移動したりしようとすると失敗する場合がある。本稿では、このような状況を回避する方法について紹介する。
作成や変更のイベントを受けて、すぐファイルを操作しようとした場合に失敗するのは、ファイルの作成や変更が開始されるタイミングでイベントの通知が発生するためだ。つまり、イベントを受け取った時点では、ほかのプロセスがまだファイルを作成中あるいは変更中のため、ファイルがロックされた状態であると考えられる。このような状況は、当然ファイルのサイズが大きいほど起こりやすい。
FileSystemWatcherクラスではファイルの作成や変更の「完了」を知ることはできないため、上記の問題を回避するには、ファイルがオープンできるようになるまで待つというのが1つの方法だ。
以下にその実装例を示す。
// watchopen.cs
using System;
using System.IO;
public class FileWatchAndOpen {
static void Main() {
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = @"c:\";
watcher.Filter = "*.*";
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Created += new FileSystemEventHandler(DoWork);
watcher.EnableRaisingEvents = true;
Console.Read(); // キー入力があるまで待つ
}
static void DoWork(object source, FileSystemEventArgs e) {
Stream st = null;
int maxCount = 10;
for (int i = 0; i < maxCount; i++) {
try {
if ((st = File.Open(
e.FullPath,
FileMode.Open,
FileAccess.Read,
FileShare.None)) != null) {
break;
}
} catch {
System.Threading.Thread.Sleep(1000);
}
}
if (st != null) {
// st.Close();
// ファイルの操作が可能
} else {
// タイムアウト
}
}
}
// コンパイル方法:csc watchopen.cs
|
|
ファイルの作成を監視し、そのファイルが利用可能になるのを待つC#のサンプル・プログラム(watchopen.cs) |
|
' watchopen.vb
Imports System
Imports System.IO
Public Class FileWatcher
Shared Sub Main()
Dim watcher As FileSystemWatcher = new FileSystemWatcher()
watcher.Path = "c:\"
watcher.Filter = "*.*"
watcher.IncludeSubdirectories = true
watcher.NotifyFilter = NotifyFilters.FileName
AddHandler watcher.Created, AddressOf DoWork
watcher.EnableRaisingEvents = true
Console.Read() ' キー入力があるまで待つ
End Sub
Shared Sub DoWork(source As object, e As FileSystemEventArgs)
Dim st As Stream = Nothing
Dim maxCount As Integer = 10
Dim i As Integer
For i = 0 To maxCount - 1
Try
st = File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None)
If Not st Is Nothing Then
Exit For
End If
Catch ex As Exception
System.Threading.Thread.Sleep(1000)
End Try
Next
If Not st Is Nothing Then
' st.Close()
' ファイルの操作が可能
Else
' タイムアウト
End If
End Sub
End Class
' コンパイル方法:vbc /r:System.dll watchopen.vb
|
|
ファイルの作成を監視し、そのファイルが利用可能になるのを待つVB.NETのサンプル・プログラム(watchopen.vb) |
|
ここでは、Fileクラス(System.IO名前空間)のOpenメソッドによりファイルのオープンを試み、失敗したら(例外が発生したら)1秒間スリープするという動作を既定回数だけ繰り返す。ファイルのオープンが成功すれば、たいていの場合は、ほかのプロセスによるそのファイルへの操作は完了していると考えてよいだろう。
もちろんこのような方法がうまくいくかどうかは、対象となっているファイルを作成あるいは変更しているアプリケーションの処理方法に依存する。それが市販アプリケーションなどの場合には、実務で利用する前に十分なテストが必要となるのはいうまでもない。
また、上記のコードでは待ち時間を合計10秒に設定しているが、作成や変更のイベントが頻繁に発生するような場合には、あまり待ち時間を長くしてしまうとFileSystemWatcherクラスの内部バッファがオーバーフローしてしまう可能性がある。このようなときにはInternalBufferSizeプロパティの値を大きめに設定するなどの対処が必要だ。
カテゴリ:クラス・ライブラリ 処理対象:ディレクトリ&ファイル
使用ライブラリ:FileSystemWatcherクラス(System.IO名前空間)
使用ライブラリ:Fileクラス(System.IO名前空間)
関連TIPS:ファイルやディレクトリの作成/変更/削除を監視するには? |
|
generated by
|
|
Insider.NET 記事ランキング
本日
月間