Ir ao conteúdo
  • Cadastre-se
jpsan

Utilizar filtro com filewatcher (c#)

Recommended Posts

Estou tentando fazer um programa de monitoramento de diretórios e o meu objetivo é para controlar arquivos de extensão ".jpg". 

O problema é que eu não estou conseguindo usar o método filter.

Segue o código do que eu fiz


using System;
using System.IO;

namespace Monitoramento_de_Arquivos_e_Sub_Pastas
{
    class Program
    {
        static private FileSystemWatcher watcher;

        static void Main(string[] args)
        {
            watcher = new FileSystemWatcher("C:\\Users\\Joao\\Desktop\\Manipula Arquivo");
            
            watcher.EnableRaisingEvents = true;
           
            watcher.Created += new FileSystemEventHandler(watcher_Created);
            watcher.Error += new ErrorEventHandler(watcher_Error);
           
            watcher.Filter("*.jpg");

            Console.ReadLine();
        }

        static void watcher_Error(object sender, ErrorEventArgs e)
        {
            Console.WriteLine(e.GetException().Message);
        }

        static void watcher_Created(object sender, FileSystemEventArgs e)
        {
            if (!File.Exists(e.FullPath))
            {
                Console.WriteLine(e.FullPath);
                //Console.WriteLine("1");
            }
        }

       
    }
}

 

O visual studio acusa o seguinte erro: non invocable member 'FileSystemWatcher.Filter' cannot be used like a method.

Agradeço muito quem ajudar. 
Desde já obrigado

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá jpsan,

 

Filter é uma propriedade, e não um método. Logo, em vez disso:

watcher.Filter("*.jpg");

escreva isso:

watcher.Filter = "*.jpg";

Além disso, você só quer escrever watcher.EnableRaisingEvents = true; depois de ter configurado o watcher por completo, senão você começa a monitorar um diretório antes de ter definido o tipo de arquivo a monitorar e os métodos para chamar ao detectar alguma mudança no diretório monitorado.

 

Percebi uma coisa estranha no seu código. Veja:

static void watcher_Created(object sender, FileSystemEventArgs e)
{
    if (!File.Exists(e.FullPath))
    {
        Console.WriteLine(e.FullPath);
        //Console.WriteLine("1");
    }
}

Aqui você só imprime o nome completo do arquivo que acabou de ser criado se ele não existir. Penso que você quis dizer algo do tipo:

static void watcher_Created(object sender, FileSystemEventArgs e)
{
    Console.WriteLine(e.FullPath);
}

Acredito que não há necessidade nem de verificar se o arquivo existe mesmo, pois o método watcher_Created só é chamado quando um arquivo é criado.

 

O código completo, com as modificações feitas, fica assim:

using System;
using System.IO;

namespace Monitoramento_de_Arquivos_e_Sub_Pastas
{
    class Program
    {
        static private FileSystemWatcher watcher;
        static void Main(string[] args)
        {
            watcher = new FileSystemWatcher("C:\\Users\\Joao\\Desktop\\Manipula Arquivo");

            watcher.Created += new FileSystemEventHandler(watcher_Created);
            watcher.Error += new ErrorEventHandler(watcher_Error);

            watcher.Filter = "*.jpg"; // essa linha mudou

            watcher.EnableRaisingEvents = true; // essa linha mudou de lugar

            Console.ReadLine();
        }
        static void watcher_Error(object sender, ErrorEventArgs e)
        {
            Console.WriteLine(e.GetException().Message);
        }
        static void watcher_Created(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine(e.FullPath); // o if desse método foi removido
        }
    }
}

 

Editado por danieltm64
  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Funcionou perfeito. Muito obrigado pela ajuda. De verdade :D. Só não entendi porque deixaram errado no site da Msdn. Mas enfim haha.

Mais uma duvida. Para ser sincero acho que eu não compreendi direito o funcionamento do FileWatcher. Criei uma classe para realizar o monitoramento do diretório e ela funcionou perfeitamente. Entretanto queria saber se existe alguma forma para eu enviar o diretorio de um arquivo encontrado para outra classe. Tentei fazer um retorno no metodo "watcher_Created", mas acredito que seja obrigatório ele ser void. então tentei fazer um metodo get para buscar este valor. Mas mesmo assim não funcionou. 
Segue o código do que eu tentei


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Destaques_do_Windows
{
    class Program
    {
        static void Main(string[] args)  //metodo Principal
        {
            MonitorarPasta mp = new MonitorarPasta("C:\\Users\\Joao\\Desktop\\Manipula Arquivo", "*.txt");

           mp.monitoraPasta(); // inicia o monitoramento do diretorio
            string dirArquivo = mp.getDirArquivo();
            Console.WriteLine(dirArquivo);


            Console.ReadLine();
        }

    }

    class MonitorarPasta
    {                     /*classe para verificar se 
                           *algum arquivo foi inserido na pasta raiz 
                           */
        private FileSystemWatcher watcher;
        private string dir;  //diretorio da pasta raiz 
        private string filtro; //filtro de monitoramento
        private string dirArquivo; //diretorio do arquivo

        public string getDirArquivo()
        {
            return dirArquivo;
        }

        public MonitorarPasta(string dir) //Construtor
        {
            this.dir = dir;
        }

        public MonitorarPasta(string dir, string filtro) //Construtor
        {
            this.dir = dir;
            this.filtro = filtro;
        }

        public void setDir(string dir)
        {
            this.dir = dir;
        }

        public string getDir()
        {
            return dir;
        }

        public void monitoraPasta()
        {
            watcher = new FileSystemWatcher(dir);

            watcher.Created += new FileSystemEventHandler(watcher_Created);
            watcher.Error += new ErrorEventHandler(watcher_Error);

            watcher.Filter = filtro; 

            watcher.EnableRaisingEvents = true; 

            //Console.ReadLine();
        }

        private void watcher_Error(object sender, ErrorEventArgs e)
        {
            Console.WriteLine(e.GetException().Message);
        }
        private void watcher_Created(object sender, FileSystemEventArgs e)
        {
            dirArquivo = e.FullPath;
            //Console.WriteLine(e.FullPath); 
        }

    }

}

class MudarExtensao
{                     /*classe para modificar a extensao 
                           *dos arquivos add
                           */

}

class VerificarResolucao
{                     /*classe para verificar a resolução
                           *de um .jpg
                           */


}

class MudarDiretorio
{                     /*classe para mudar o diretorio
                           *de um arquivo para outro local
                           */


}



Mais uma vez obrigado

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vamos lá.

 

O nome que você escolheu para a sua classe não é ideal. Uma classe representa uma "coisa" ou "entidade", enquanto um método representa uma "ação" ou "operação". Pense em uma classe como um substantivo e pense em um método como um verbo. O nome que você escolher deve caber nesse formato. Então em vez de chamar sua classe de MonitorarPasta, talvez o nome MonitoradorDePasta seja melhor.

 

Já os nomes que você escolheu para os métodos da classe MonitorarPasta não seguem o estilo de código convencional do C#. Em C#, nome de método normalmente começa com letra maiúscula, ao contrário do que se tem em Java, onde nome de método normalmente começa com letra minúscula. Assim, sugiro que você renomeie o método monitoraPasta para MonitorarPasta.

 

Em C#, quando você deseja acessar algum dado de um objeto, não é comum usar métodos cujo nome começa com "get". Por exemplo, se você tem uma classe Pessoa, normalmente você não acessa o nome e a idade com métodos getNome e getIdade, e sim com propriedades. Uma propriedade nada mais é do que um método do tipo "get" e um método do tipo "set" com a mesma sintaxe de um atributo normal. No exemplo da classe Pessoa, você teria a propriedade Nome e a propriedade Idade, que seriam usados assim:

// Exemplo de como usar propriedades com uma classe fictícia
Pessoa pessoa = new Pessoa();

// usando propriedade pública para alterar um atributo privado.
pessoa.Nome = "Luís";
pessoa.Idade = 25;

// usando propriedade pública para ler um atributo privado.
Console.WriteLine(pessoa.Nome + " tem " + pessoa.Idade + " anos de idade.");

Assim, você acessa o dado não através de dois métodos mas através de uma propriedade, e essa propriedade sabe como ler e alterar o dado. No seu caso, você deveria colocar o diretório e o filtro como propriedades em vez de métodos. Fica assim:

// atributos privados
private string diretorio;
private string filtro;

// propriedades públicas
public string Diretorio { get { return diretorio; } set { diretorio = value; } }
public string Filtro { get { return filtro; } set { filtro = value; } }

Na parte "get" você retorna o valor do atributo, e na parte "set" você altera o valor do atributo.

 

Notei que você inicializa e prepara o watcher no método monitorarPasta, sendo que isso deveria ir no construtor, pois o construtor roda só uma vez, já o método monitorarPasta pode ser chamado várias vezes. Como é possível que o usuário da sua classe altere o diretório e o filtro antes de chamar o método monitorarPasta, é correto atualizar o diretório e o filtro do watcher nesse método.

 

Não tenho certeza, mas acho que o que você queria era imprimir o nome completo do arquivo que foi criado, mas utilizando um objeto intermediário em vez de usar o FileSystemWatcher diretamente. O erro é que você inicia o monitoramento e logo em seguida você tenta acessar o nome do arquivo que foi criado, sendo que nenhum arquivo foi criado no curtíssimo intervalo de tempo entre começar o monitoramento e tentar acessar o nome do arquivo. Em vez disso, você deveria ter um evento em sua classe MonitorarPasta que é levantado quando o watcher detecta que um arquivo foi criado. Depois, no Main, após instanciar mp, você deve associar o evento de mp com métodos da classe Program. Assim, quando o objeto mp detectar a criação de um arquivo (através do watcher interno), um método é chamado e imprime o nome completo do arquivo.

 

O código com todas as modificações fica assim:

using System;
using System.IO;

namespace Destaques_do_Windows
{
    class Program
    {
        static void Main(string[] args)
        {
            MonitoradorDePasta mp = new MonitoradorDePasta("C:\\Users\\Joao\\Desktop\\Manipula Arquivo", "*.txt");
            mp.ArquivoCriado += new MonitoradorDePasta.ArquivoCriadoEventHandler(mp_ArquivoCriado);
            mp.MonitorarPasta();

            Console.ReadLine();
        }
        static void mp_ArquivoCriado(object sender, string nomeCompleto)
        {
            Console.WriteLine(nomeCompleto);
        }
    }
    class MonitoradorDePasta
    {
        private FileSystemWatcher watcher;
        private string diretorio;
        private string filtro;
        public string Diretorio { get { return diretorio; } set { diretorio = value; } }
        public string Filtro { get { return filtro; } set { filtro = value; } }
        public delegate void ArquivoCriadoEventHandler(object sender, string nomeCompleto);
        public event ArquivoCriadoEventHandler ArquivoCriado;
        public MonitoradorDePasta(string diretorio, string filtro)
        {
            this.diretorio = diretorio;
            this.filtro = filtro;

            watcher = new FileSystemWatcher(diretorio, filtro);

            watcher.Created += new FileSystemEventHandler(watcher_Created);
            watcher.Error += new ErrorEventHandler(watcher_Error);
        }
        public void MonitorarPasta()
        {
            watcher.Path = diretorio;
            watcher.Filter = filtro;
            watcher.EnableRaisingEvents = true;
        }
        private void watcher_Error(object sender, ErrorEventArgs e)
        {
            Console.WriteLine(e.GetException().Message);
        }
        private void watcher_Created(object sender, FileSystemEventArgs e)
        {
            ArquivoCriado(this, e.FullPath);
        }
    }
}

Como escrevo a maior parte do meu código em inglês, tem alguns termos em inglês que eu não sei a tradução portuguesa adotada na literatura brasileira. Por exemplo, delegates ("intermediários"?) têm nomes que normalmente terminam com Handler ("Lidador"?), mas não sei a tradução amplamente aceita, então no código que eu coloquei, chamei um delegate de ArquivoCriadoEventHandler. Enfim, adapte o código como preferir.

 

Espero ter ajudado.

Editado por danieltm64

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá danieltm64 tudo certo? Por acaso você é professor? Tu tem uma didática muito boa. Parabéns.

 

Voltando ao assunto do tópico, caramba, quantos conceitos eu ainda tenho que aprender... hehe. Delegate por exemplo eu nunca tinha ouvido falar. Minha maior duvida no momento é sobre o método  mp_ArquivoCriado da classe program. Ele é um método que referencia outra classe? Me lembrou ponteiro, porque eu uso ele uma classe baseado no que acontece em outra? Outra coisa, eu posso utilizar um objeto dentro desse método, que foi instanciado no main?


 class Program
    {
        static void Main(string[] args)
        {
            MonitoradorDePasta mp = new MonitoradorDePasta("C:\\Users\\Joao\\Desktop\\Manipula Arquivo", "*.txt");

            RemomeadorDeExtensao re = new RemomeadorDeExtensao(); //!!!

            mp.ArquivoCriado += new MonitoradorDePasta.ArquivoCriadoEventHandler(mp_ArquivoCriado);
            mp.MonitorarPasta();

            Console.ReadLine();
        }
        static void mp_ArquivoCriado(object sender, string nomeCompleto)
        {
            re.Diretorio(nomeCompleto); //!!!!
        }
    }

 

class RemomeadorDeExtensao
    {                     /*classe para modificar a extensao 
                           *dos arquivos add
                           */
        private string dirNovoArq;
        
        public string DirNovoArq  //propriedade que pega o diretorio de um novo arquivo
        {
            set
            {
                dirNovoArq = value;
            }
            get
            {
                return dirNovoArq;
            }
        }  
        
        public void ImprimeDir()
        {
            Console.WriteLine(dirNovoArq);
        }


 

Omiti o resto do código que já foi corrigido para ficar mais fácil a visualização. Comentei com //!! as linhas que eu adicionei.

att
João
 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×