2016-07-21 3 views
1

Я контролирую событие для создания файлов (копирование) с помощью FileSystem Watcher. Я хочу, чтобы программа обрабатывала файлы изображений.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 даже когда действительный файл изображения скопированные, который я думаю, происходит потому, что событие было до того, как файл был полностью скопирован. Как я могу это преодолеть? Я хочу только добавить действительные файлы изображений в список дел, и я буду обрабатывать эти изображения по одному позже.

+0

код, по-видимому, не имеет линии, которая может выкинуть из памяти. Скорее всего, ваша «// моя обработка с изображением» бросает эту ошибку. Вы можете добавить ожидание 1 сек, если вы чувствуете, что файл еще не полностью скопирован. – puneet

+0

@puneet 'using (Bitmap test = new Bitmap (Bitmap.FromFile (e.FullPath))) – techno

+0

Я устанавливаю' watcher.NotifyFilter = NotifyFilters.FileName; 'и для загрузки изображения я использую' Image.FromFile (e.FullPath); и он работает без каких-либо исключений. –

ответ

1

Может быть, это немного более чистое решение, чем Try-Catch. Im, используя этот код без каких-либо исключений.

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 Мб (im совершенно уверен и больше).

Если этот код не работает для вас, отправьте исключение, а не загрузите его.

+0

Спасибо ... Я постараюсь и вернусь ... btw i did not downvote :) – techno

+0

Это не позволяет правильно определить некоторые jpg-изображения. – techno

+0

Можете ли вы привести мне пример? Магический номер для jpg должен начинаться с 'FFd8'. Указано [здесь] (http://stackoverflow.com/a/8755028/4558029) несколько раз – lokusking

0

Для первого требования: «Я только хочу, чтобы программа обработки файлов изображений»

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 
    } 
} 

Для второго требования: «Вне Exception памяти»

Вот что происходит, когда файл (только имя файла и некоторые атрибуты) система вызывает созданное событие. Затем событие с измененным файлом также называется

Итак, вам нужно выполнить обработку в измененном событии. Также, чтобы предотвратить дублирование вызова, вам нужно добавить фильтр к наблюдателю.

Полный код.

private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e) 
     { 

      FileInfo fileInfo = new FileInfo(e.FullPath); 
      string strFileExt = fileInfo.Extension; 

      // filter file types 
      if (Regex.IsMatch(strFileExt, @"\.png|\.jpg", RegexOptions.IgnoreCase)) 
      { 
       //here Process the image file 
       try 
       { 
        using (Bitmap test = new Bitmap(Bitmap.FromFile(e.FullPath))) 
        { 
         //Do your code here. 
        } 
       } 
       catch (Exception error) 
       { 
        Console.WriteLine("File Error"); 
       } 
      } 


     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      fileSystemWatcher1.Path = @"C:\Users\Christlin\Desktop\res"; 

      //To Prevent duplicated calling of changed event 
      fileSystemWatcher1.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size; 
     } 
+0

Спасибо ... вы подключились к измененному событию и создали событие ... я должен подключиться к обоим событиям? – techno

+0

Исходя из требований ОП, этого может быть недостаточно. Например, я мог бы легко замаскировать изображение, предоставив ему другое расширение (например, '.txt'). –

+0

@techno изменений и событий Form1_Load достаточно только –