C# FileSystemWatcher 监视磁盘文件变更
简化需求:有一个简化了的需求是这样的:有一个拍照程序在运行,一旦抓拍之后则将图片文件存储至某目录,然后图片要上传至远程服务器并update数据库。
原需求:原先的需求是这样的:有一台PDA扫码枪,一个IP照相机放置在下线区传送带上方。当PDA扫描箱子上的条码,触发相机拍照,将图片流传至远端服务器,找到对应的条码,将图片存储并更新数据库。
然而我不知道PDA扫描的瞬间如何与IP相机通信(蓝牙或WLAN?),其实关键是我不知道怎样使用IP相机的外触发功能,增加蓝牙触发器?也不知道怎样hack或ssh到这个相机(应该是linux的吧),所以只能先使用简化需求的版本。
而简化需求的版本,关键就是监视文件夹内容变化与上传文件流。
昨天问了下度娘,C#中的监视组件名字叫做FileSystemWatcher。
于是写了个demo,可以监视所有逻辑盘或者某个文件夹。
使用方法:
1.直接打开是监视所有逻辑磁盘文件变化。
2.或者传递参数,监视某一路径文件变化。如图,监视e盘
源代码:
1 namespace FileSystemWatcherDemo 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //watcher组 8 FileSystemWatcher[] watchers; 9 10 //若未传递参数,则监视所有文件系统,包括CD-ROM(不可用),可移动磁盘(不可用)等 11 if (args.Length == 0) 12 { 13 string[] drivers = Directory.GetLogicalDrives(); 14 watchers = new FileSystemWatcher[drivers.Length]; 15 16 for (int i = 0; i < drivers.Length; i++) 17 { 18 try 19 { 20 watchers[i] = new FileSystemWatcher { Path = drivers[i] }; 21 } 22 catch (Exception ex) 23 { 24 Trace.TraceWarning(ex.Message); 25 } 26 } 27 } 28 else 29 { 30 watchers = new FileSystemWatcher[1]; 31 watchers[0] = new FileSystemWatcher { Path = args[0] }; 32 } 33 34 foreach (FileSystemWatcher w in watchers) 35 { 36 if (w == null) continue; 37 38 w.Filter = "*"; 39 w.IncludeSubdirectories = true; 40 w.EnableRaisingEvents = true; 41 42 w.Created += onFileSystem_Changed; 43 w.Deleted += onFileSystem_Changed; 44 w.Changed += onFileSystem_Changed; 45 w.Renamed += watcher_Renamed; 46 } 47 48 Console.ReadLine(); 49 } 50 51 #region [ 检测文件是否占用 ] 52 /// <summary> 53 /// 检测文件是否占用 54 /// </summary> 55 /// <param name="filename"></param> 56 /// <returns></returns> 57 static bool IsFileReady(string filename) 58 { 59 var fi = new FileInfo(filename); 60 FileStream fs = null; 61 try 62 { 63 fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.None); 64 return true; 65 } 66 catch (IOException) 67 { 68 return false; 69 } 70 71 finally 72 { 73 if (fs != null) 74 fs.Close(); 75 } 76 } 77 #endregion 78 79 private static volatile object _lock = true; 80 static void onFileSystem_Changed(object sender, FileSystemEventArgs e) 81 { 82 lock (_lock) 83 { 84 Console.ForegroundColor = ConsoleColor.DarkGray; 85 Console.Write("["); 86 Console.Write(DateTime.Now.ToString("HH:mm:ss")); 87 Console.Write("] "); 88 89 switch (e.ChangeType.ToString().ToLower()) 90 { 91 case "created": 92 //while (!IsFileReady(e.FullPath)) 93 //{ 94 // if (!File.Exists(e.FullPath)) 95 // return; 96 // Thread.Sleep(100); 97 //} 98 Console.ForegroundColor = ConsoleColor.Green; 99 Console.Write(e.ChangeType); 100 Console.ForegroundColor = ConsoleColor.White; 101 Console.Write(" "); 102 Console.Write(e.Name); 103 Console.Write(" "); 104 Console.ForegroundColor = ConsoleColor.DarkGray; 105 Console.Write(e.FullPath); 106 107 break; 108 case "deleted": 109 Console.ForegroundColor = ConsoleColor.Red; 110 Console.Write(e.ChangeType); 111 Console.ForegroundColor = ConsoleColor.White; 112 Console.Write(" "); 113 Console.Write(e.Name); 114 Console.Write(" "); 115 Console.ForegroundColor = ConsoleColor.DarkGray; 116 Console.Write(e.FullPath); 117 break; 118 case "changed": 119 Console.ForegroundColor = ConsoleColor.Cyan; 120 Console.Write(e.ChangeType); 121 Console.ForegroundColor = ConsoleColor.White; 122 Console.Write(" "); 123 Console.Write(e.Name); 124 Console.Write(" "); 125 Console.ForegroundColor = ConsoleColor.DarkGray; 126 Console.Write(e.FullPath); 127 break; 128 } 129 130 Console.Write("\r\n"); 131 } 132 } 133 static void watcher_Renamed(object sender, RenamedEventArgs e) 134 { 135 Console.ForegroundColor = ConsoleColor.Magenta; 136 Console.Write(e.ChangeType); 137 Console.ForegroundColor = ConsoleColor.White; 138 Console.Write(" "); 139 Console.Write(e.OldName); 140 Console.Write(e.OldFullPath); 141 Console.ForegroundColor = ConsoleColor.Yellow; 142 Console.Write(" "); 143 Console.Write(e.Name); 144 Console.Write(e.FullPath); 145 Console.Write(Thread.CurrentThread.Name); 146 Console.Write("\r\n"); 147 } 148 } 149 }
仍有bug,望高手指正。
附上编译好的exe,可以直接运行。
http://lison.cc