读书人

FileSystemWatcher对象Created事件处理

发布时间: 2012-07-04 19:33:55 作者: rapoo

FileSystemWatcher对象Created事件处理问题
各位大侠:
我想做一个文件监控程序,当监控文件夹下有新的txt文件产生时,对文件进行读写操作,完成数据读取和相关计算后把该文件转存到其它目录,原文件删除。
我自己写的created事件 是先获取监控文件下的所有文件,然后对文件列表中的文件进行逐个处理,最后转存txt文件。处理完成后监控文件夹应为空,等待下一时次资料的处理。
自己遇到的问题:
1、测试的时候,我往监控文件夹复制n个txt文件,结果产生了n次created事件,导致程序被重复处理了n次。
我想要的结果是:当有多个txt文件被创建时,在一个created事件中处理所有的文件。
或是每个created事件都处理相应产生的txt文件,但不知道怎样才能获取到产生created事件的相应文件的文件名。

网上还说,利用created事件对文件进行读写操作,会遇到一些异常,比如其他程序在使用,或是文件还在被创建的过程当中。网上说的解决方法也很复杂,都看不懂。我自己试了下,复制2个txt文件,在created事件中写读整个txt文件,运行正常。可能是我的txt文件比较小吧,但还是想在程序方面做相应处理。

C# code
namespace 文件监控入库{    class Program    {        static void Main(string[] args)        {            string MonitorPath;            MonitorPath = System.Environment.CurrentDirectory+"\\待入库文件1";            WatcherStrat(@MonitorPath , "*.txt");            Console.ReadKey();        }        private static void WatcherStrat(string path, string filter)                {                        FileSystemWatcher watcher = new FileSystemWatcher();            watcher.Path = path; //不知道怎么设置监控多个目录            watcher.Filter = filter;            watcher.Created += new FileSystemEventHandler(OnCreated);            watcher.EnableRaisingEvents = true;        }                              private static void OnCreated(object source, FileSystemEventArgs e)        {                                 //获取程序当前路径和文件列表            string filedir, filepath;            string[] filelist;            filedir = System.Environment.CurrentDirectory + "\\待入库文件1";            DirectoryInfo dir = new DirectoryInfo(filedir); //实例化directoryInf类            FileSystemInfo[] f = dir.GetFileSystemInfos(); //获取监控目录下的文件名称            filelist = new string[f.Length];            for (int i=0;i<f.Length ;i++)             {                filelist[i] = filedir + "\\"+f[i].ToString () ;                Console.WriteLine(filelist[i]);//输出文件名,调试用的,看正不正常                RedData(filelist[i].ToString ());//相应文件读取函数            }           }                public static void RedData(string filepath)        {            //读取单个文件  测试            StreamReader sr = new StreamReader(filepath );            while (sr.ReadLine ()!=null )            {                                Console .WriteLine (sr.ReadLine ().ToString ());            }            sr.Close();            //将读取的资料写入数据库            //............        }        public static void CopyFile(string filepath)        {            //复制转移已入库报文        }    }}


[解决办法]
RedData 写法也不对,ReadLine 是立即返回的,不能 while 条件里调用一次,内部再调用一次,这样不仅漏掉一半,而且很可能条件里能返回,循环内就结束返回 null 了,这时再调用 ToString 就 NullReferenceException 异常,假如文件大,可能写的那边还没完,这边就开始读,出现“该进程无法访问该文件”,可以等待并重试一些次数
C# code
public static void RedData(string filepath){    Stream stream;    int index = 0;    while (true)    {        try        {            stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.None);            break;        }        catch (Exception)        {            if (index++ > 5)            {                throw;            }            else            {                Thread.Sleep(1000);            }        }    }    //读取单个文件  测试    StreamReader sr = new StreamReader(stream);    string tr = null;    while ((tr = sr.ReadLine()) != null)    {        Console.WriteLine(tr);    }    sr.Close();    stream.Dispose();    //将读取的资料写入数据库    //............} 

读书人网 >C#

热点推荐