FileSystem Watcher-检查复制的文件是否为Image

时间:2016-07-21 04:23:50

标签: c# .net filesystemwatcher

我正在使用FileSystem Watcher监视文件夹创建文件(复制)事件。我只希望程序处理图像文件。

FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Filter = "*.*";
watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
watcher.Path = path;

所以我尝试创建一个Bitmap,并在抛出异常时避开该文件

private static void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
    try
    {
        using (Bitmap test = new Bitmap(Bitmap.FromFile(e.FullPath)))
        {
            mytoprocesslist.add(e.FullPath);
        }

        //do my processing with image 
        Console.WriteLine(e.FullPath);
    }
    catch (Exception error)
    {
       Console.WriteLine("File Error");
    }
 }

即使复制了有效的图像文件,也会抛出Out of Memory exception,我认为这是因为在完全复制文件之前引发了事件。我怎么能克服这个?我只想将有效的图像文件添加到待办事项列表中,我将逐个处理这些图像。

2 个答案:

答案 0 :(得分:1)

比Try-Catch更清洁的解决方案可能是这个。 我使用此代码时没有任何异常。

private static bool IsImage(string path) {
      try {
        var result = false;

        using (var stream = new FileStream(path, FileMode.Open)) {
          stream.Seek(0, SeekOrigin.Begin);

          var jpg = new List<string> { "FF", "D8" };
          var bmp = new List<string> { "42", "4D" };
          var gif = new List<string> { "47", "49", "46" };
          var png = new List<string> { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" };
          var imgTypes = new List<List<string>> { jpg, bmp, gif, png };

          var bytesIterated = new List<string>();

          for (var i = 0; i < 8; i++) {
            var bit = stream.ReadByte().ToString("X2");
            bytesIterated.Add(bit);

            var isImage = imgTypes.Any(img => !img.Except(bytesIterated).Any());
            if (isImage) {
              result = true;
              break;
            }
          }
        }
        return result;
      } catch (UnauthorizedAccessException) {
        return false;
      }
    }

代码的使用

foreach (var file in Directory.EnumerateFiles(@"pathToFlowersFolder"))
            {
                Console.WriteLine($"File: {file} Result:{IsImage(file)}");
            }

修改

玩完之后我得到了一个IO-Exception(文件已经在使用中)
阅读this后,我将为您提供以下解决方案:

private void button1_Click(object sender, EventArgs e)
        {
            var watcher = new FileSystemWatcher();
            watcher.Created += new FileSystemEventHandler(fileSystemWatcher1_Changed);
            watcher.Path = @"c:\temp";
            watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
            watcher.EnableRaisingEvents = true;
        }

        private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            Thread.Sleep(100); // <- give the Creator some time. Increase value for greate pause
            if (IsImage(e.FullPath))
            {
                Console.WriteLine("success----------->" + e.FullPath);
            }
        }

注意

这段代码适用于我的机器。我的硬盘是SSD,因此您可能需要增加线程休眠时间。它适用于所有图像(jpg,bmp,gif,png),最大尺寸为7 Mb(我非常肯定和更高)。

如果此代码不适合您,请发布例外而非上传您的代码。

答案 1 :(得分:0)

对于第一个要求:“我只希望程序处理图像文件”

on

对于第二个要求:“Out of Memory Exception”

这里发生的是,当创建文件时(仅文件名和一些属性),系统正在调用创建的事件。然后文件更改事件也称为

所以你必须在改变的事件中进行处理。另外,为防止重复呼叫,您必须向观察者添加过滤器。

以下是完整的代码。

private static void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
{
  string strFileExt = getFileExt(e.FullPath); 

  // filter file types 
  if (Regex.IsMatch(strFileExt, @"\.png|\.jpg", RegexOptions.IgnoreCase)) 
  { 
      //here Process the image file 
  }
}