.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プロパティの値を大きめに設定するなどの対処が必要だ。End of Article

カテゴリ:クラス・ライブラリ 処理対象:ディレクトリ&ファイル
使用ライブラリ:FileSystemWatcherクラス(System.IO名前空間)
使用ライブラリ:Fileクラス(System.IO名前空間)
関連TIPS:
ファイルやディレクトリの作成/変更/削除を監視するには?
 
この記事と関連性の高い別の.NET TIPS
ファイルやディレクトリの作成/変更/削除を監視するには?
Windowsアプリケーションでファイルやディレクトリを監視するには?
オープン中のファイルにアクセスするには?
[ASP.NET]ページから生成されたソース・コードを見るには?
ファイルをコピー/削除/リネーム/移動するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間