WP TIPS に戻る

分離ストレージのファイルの入っているフォルダを削除する

サンプルプロジェクト deletedirectory_containing_files.zip

WP7 ローカルファイルは分離ストレージに格納する仕様になっています。
分離ストレージは Silverlight 独自の仕様で、通常のストレージのようにファイルやフォルダの作成読み込みなどが出来ますが、一部備わっていないメソッドや機能などがあります (FileInfo, DirectoryInfo クラスが使用できません)。
比較的困るのが ファイルの入っているフォルダを削除できない という件があります。通常の C# などでは DirectoryInfo.DeleteDirectory(path, recursive) とすることで、入っているファイルごとフォルダを削除することが出来ますが、WP7 ではサポートされていません。

IsolatedStorageFile.Remove() というメソッドはあるのですが、このメソッドは分離ストレージに記録されているすべてを削除してしまうので、指定したパスだけを消す機能はありません。

やはり指定したパス以下のファイルとフォルダを再帰的に削除はしたいもの。たとえばこんな感じ。

IsolatedStorageFile.GetUserStoreForApplication().RemoveDirectory(this.dir);

このようなときは以下のコードを使用すると、指定したパス以下のファイルとフォルダを削除することが出来ます。

  1. 指定したパス以下のファイルとフォルダを見つけるクラス
    /// <summary>
    /// StorageRecursiveEventHandler のイベント変数
    /// </summary>
    public class StorageRecursiveEventArgs : EventArgs
    {
       public IsolatedStorageFile IsolatedStorageFile;
       public string Filename;
       public string Foldername;
    }
    
    /// <summary>
    /// ファイルかフォルダごとに発生するイベントのイベントハンドラ
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void StorageRecursiveEventHandler(object sender, StorageRecursiveEventArgs e);
    
    /// <summary>
    /// IsolatedStorage の指定したフォルダ以下のファイルとフォルダごとにイベントを発生させるクラス
    /// </summary>
    public class StorageRecursive
    {
    
       public event StorageRecursiveEventHandler GotFile;
       public event StorageRecursiveEventHandler GotFolder;
    
       public void Start(string srcdir, bool recurse)
       {
           // /Shared は無視する
           if (srcdir.StartsWith("Shared") || srcdir.StartsWith("/Shared"))
           {
               return;
           }
    
           try
           {
               using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
               {
                   // 指定されたフォルダ配下のファイル名を取得する
                   string searchPattern = System.IO.Path.Combine(srcdir, @"*.*");
                   string[] files = iso.GetFileNames(searchPattern);
    
                   // すべてのファイルサイズを加算する
                   foreach (string file in files)
                   {
                       // 開くファイルのパスを生成
                       string filename = Path.Combine(srcdir, file);
                       //  System.Diagnostics.Debug.WriteLine(filename);
                       
                       // イベント発火
                       if (this.GotFile != null)
                           this.GotFile(this, new StorageRecursiveEventArgs { Filename = filename, IsolatedStorageFile = iso });
                   }
    
                   // 指定されたフォルダ配下のフォルダ名を取得する
                   if (recurse)
                   {
                       string[] dirs = iso.GetDirectoryNames(searchPattern);
    
                       // すべてのフォルダ内のファイルサイズを加算する
                       foreach (string dir in dirs)
                       {
                           // 開くフォルダのパスを生成
                           string dirname = Path.Combine(srcdir, dir);
                           //  System.Diagnostics.Debug.WriteLine(dirname);
    
                           // イベント発火
                           if (this.GotFolder != null)
                               this.GotFolder(this, new StorageRecursiveEventArgs { Foldername = dirname, IsolatedStorageFile = iso });
    
                           // さらに取得する
                           Start(dirname, recurse);
                       }
                   }
    
               }
    
               return;
           }
           catch
           {
               return;
           }
       }
    }
  2. 上記クラスを使用したフォルダ削除の拡張メソッド
    public static class IsolatedStorageExtentions
    {
       /// <summary>
       /// 指定したパスのフォルダと含まれているファイルとフォルダすべてを削除します。
       /// </summary>
       /// <param name="path"></param>
       /// <returns></returns>
       public static bool RemoveDirectory(this IsolatedStorageFile iso, string path)
       {
           try
           {
               // フォルダ内にファイルやフォルダが残っていると、例外が発生するので
               // 1. まずすべてのファイルを削除する
               // 2. すべてのフォルダパスをリストに入れておく
               // 3. リストを逆順にソートする(パス名の長い順にする)
               // 4. リストのフォルダを削除する
               // という手順でフォルダの削除を行う。
               
               // フォルダがない
               if (!iso.DirectoryExists(path))
                   return true;
    
               // 最初はファイルだけ削除する
               StorageRecursive r = new StorageRecursive();
               r.GotFile += (s, args) =>
               {
                   iso.DeleteFile(args.Filename);
               };
               r.Start(path, true);
    
               // フォルダ名を取得する
               List<string> dirs = new List<string>();
               r.GotFolder += (s, args) =>
               {
                   dirs.Add(args.Foldername);
               };
               r.Start(path, true);
    
               // 取得したフォルダを削除する - パスの長い順にする
               dirs.Reverse();
               foreach (string dir in dirs)
               {
                   iso.DeleteDirectory(dir);
               }
    
               // 指定したフォルダを削除する
               iso.DeleteDirectory(path);
    
               // 返す
               return true;
           }
           catch (Exception ex)
           {
               return false;
           }
       }
           
    }