Tuesday, July 27, 2010

FileSystemWatcher для джуніора

Intro

Сьогодні на роботі переді мною повстало завдання, написати код який мав би слідкував за певною директорією і при додаванні, чи видаленні файлів з неї, записував список файлів в xml документ.

Першою думкою було написати евент, який при кожній активності користувача в програмі обновляв би список файлів і створював відповідну хмлку. Я навіть не встиг потішитись з такого швидкого вирішення проблеми як мене перебили і сказали що для цього можу використати FileSystemWatcher та дали ссилку на мсдн. В цей момент ейфорія розвіялась я опустився на землю і ще раз переконався в тому що я JUNIOR.



Code



using System;

using System.IO;

using System.Security.Permissions;



namespace Wizard.BizLogic

{

  public class FolderWatcher

  {

    /// <summary>

    /// Sets the folder to watch

    /// </summary>

    /// <param name="path">Patch to the folder</param>

    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]

    public static void WatchFolder(string path)

    {

      FileSystemWatcher watcher = new FileSystemWatcher();

      watcher.Path = path;

      watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite

        | NotifyFilters.FileName | NotifyFilters.DirectoryName;



      watcher.Filter = "*.xml";

      watcher.IncludeSubdirectories = true;



      watcher.Created += new FileSystemEventHandler(onChanged);

      watcher.Deleted += new FileSystemEventHandler(onChanged);

      watcher.Renamed += new RenamedEventHandler(onRenamed);



      watcher.EnableRaisingEvents = true;

    }



    private static void onChanged(object source, FileSystemEventArgs e)

    {

      string fullPath = e.FullPath;

      DirectoryInfo directoryInfo = Directory.GetParent(fullPath);

      string[] strings = e.Name.Split("\\");

      if (strings[1] != directoryInfo.Name + ".xml")

      {

        string xmlFileList = MigrationSchemaLogic.GetXMLFileList(directoryInfo.FullName);

      }

    }



    private static void onRenamed(object source, RenamedEventArgs e)

    {

      string fullPath = e.FullPath;

      DirectoryInfo directoryInfo = Directory.GetParent(fullPath);

      string[] strings = e.Name.Split("
\\");

      if (strings[1] != directoryInfo.Name + ".xml")

      {

        string xmlFileList = MigrationSchemaLogic.GetXMLFileList(directoryInfo.FullName);

      }

    }

  }

}





* This source code was highlighted with Source Code Highlighter.


Тут все просто, в класі є три методи, всі вони статичні, але лише до одного з них є доступ з зовні, це WatchFolder(string path) який на вхід приймає стрічку з адресою папки типу "C:\temp". Далі створюється об'єкт watcher, для якого ми задаємо фільтри при яких він буде спрацьовувати (тут детальніше) і при винекненні певних змін в каталозі будуть відповідно викликатись методи

watcher.Created += new FileSystemEventHandler(onChanged);

watcher.Deleted += new FileSystemEventHandler(onChanged);

watcher.Renamed += new RenamedEventHandler(onRenamed);

В мене в методах зроблена перевірка на те якщо зміни відбулись в моїй хмлці то ми їх ігноруємо, якщо ні то викликаємо метод для перерахунку файлів у каталозі.

Код максимально простий і думаю для вас не буде важко його використати. Викликається він просто "FolderWatcher.WatchFolder(c:\Windows)" а для отримання практичного результату необхідно створити свій метод і визвати його замість

"string xmlFileList = MigrationSchemaLogic.GetXMLFileList(directoryInfo.FullName);".



GetXMLFileList Listing:

public static string GetXMLFileList(string directory)

    {

      StringWriter writerString = new StringWriter();

      XmlTextWriter writer = new XmlTextWriter(writerString);

      writer.WriteStartDocument(true);

      bool bFirst = true;

      DirectoryInfo dir = new DirectoryInfo(directory);

      if (dir.GetFiles("*.xml").Count() > 0)

      {

        foreach (FileInfo entry in dir.GetFiles("*.xml"))

        {

          if (bFirst)

          {

            writer.WriteStartElement("XMLFilesList", string.Empty);



            string strFullName = entry.FullName;

            string strFileName = entry.Name;

            string strDir = strFullName.Substring(0, strFullName.Length - strFileName.Length);



            writer.WriteAttributeString("Directory", strDir);

            bFirst = false;

          }

          if (entry.Name != dir.Name + ".xml")

          {

            writer.WriteStartElement("file", string.Empty);



            writer.WriteElementString("FileName", entry.Name);

            writer.WriteElementString("Path", String.Concat(@"..\..\..\Xml\", entry.Name));



            writer.WriteEndElement();

          }

        }



        writer.WriteEndElement();

        writer.WriteEndDocument();

      }

      //FileStream fs = File.Open(directory + "
\\" + dir.Name + ".xml", FileMode.Create, FileAccess.Write);

      FileStream fs = File.Open(String.Concat(directory, "
\\", dir.Name, ".xml"), FileMode.Create, FileAccess.Write);

      StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);



      sw.WriteLine(writerString.ToString());



      sw.Flush();

      sw.Close();

      return writerString.ToString();

    }



* This source code was highlighted with Source Code Highlighter.


PS

Хоча я й був розчарований своїм незнанням, я дуже зрадів що можу вивчити щось нове, нехай таке маленьке й незначне але все-одно це ще один сантиметр на шляху до успіху. Пам'ятайте : "Одні люди перед собою бачить проблеми, а інші можливості" кожна проблема це можливість вивчити щось нове так що не втрачайте їх.

Дякую за увагу.

No comments:

Post a Comment