C# - Lendo arquivos textos delimitados com LINQ


Este artigo mostra como ler um arquivo texto delimitado usando LINQ. (só isso...)

Como exemplo eu vou usar um arquivo texto delimitado por vírgula com a seguinte informação:

O arquivo vai ter o nome de Clientes.txt e terá o seguinte conteúdo:

Jose C Macoratti,macoratti@yahoo.com,Brasilia,Brasil
Jefferson A Ribeiro,jeff@net.com.br,London,Great Britain
Janice Lima,janicer@rad.com,Nevada,USA
Miriam Maquila,miriam@net.com,Madri,Spain
Jessica Lang,jessicalang@trop.net,Toronto,Canada
Yuri Jemming,yuri@trop.net,California,USA

Antes de começar a leitura do arquivo texto vamos criar uma classe que irá tratar os registros que vamos ler a partir do arquivo texto.

Para isso vamos criar uma classe Cliente conforme abaixo:

public class Cliente
{
   public string Nome { get; set; }
   public string Email { get; set; }
   public string cidade { get; set; }
   public string Pais { get; set; }
}

Com isso estamos pronto para ler os dados a partir do nosso arquivo usando LINQ.

Vamos ler o arquivo inteiro e exibir o resultado usando o seguinte código:

void BtnLerClick(object sender, EventArgs e)
{
              string caminhoArquivo = "C:\\dados\\Clientes.txt";
              var consulta =
              from linha in File.ReadAllLines(caminhoArquivo)
              let clienteDados = linha.Split(',')
              select new Cliente()
              {
                   Nome = clienteDados[0],
                   Email = clienteDados[1],
                   Cidade = clienteDados[2],
                   Pais = clienteDados[3],
              };
			
            foreach (var item in consulta)
            {
	lstTexto.Items.Add(item.Nome +","+ item.Email + ","+ item.Cidade + ","+ item.Pais);
             }
}

O comando File.ReadAllLines() retorna um array de linhas, usamos então a função Split para separar os registros pela vírgula.

Overloads Public Function Split(ParamArray Char() AS String) - Este método identifica as substrings presentes em uma string que são delimitadas por um ou mais caracteres específicos em uma matriz , extrai as substrings e as coloca em uma matriz de strings.

Overloads Public Function Split(Char(), Integer) As String() - Este método identifica as substrings presentes em uma string que são delimitadas por um ou mais caracteres específicos em uma matriz , extrai as substrings e as coloca em uma matriz de strings. O inteiro é o parâmetro que especifica o número máximo de elementos da matriz a retornar.

O Método File.ReadAllLines (String)

Abre um arquivo de texto, lê todas as linhas do arquivo e, em seguida, fecha o arquivo.
Retorna uma matriz de strings que contém todas as linhas do arquivo lido.

public static string[] ReadAllLines( string path )

Obs:Para arquivos muito grandes este método tem uma execução lenta.

O Método StreamReader.ReadLine

Lê uma linha de caracteres do fluxo atual e retorna os dados como uma cadeia de Caracteres.
Retorna a próxima linha do fluxo de dados ou uma referência Null (Nothing no VB) se o final do arquivo
for alcançado.

Podemos também filtrar a leitura lendo somente os clientes de um determinado país:

var consulta =
             from c in
            (from linha in File.ReadAllLines(caminhoArquivo)
             let clientesDados = linha.Split(',')
             select new Cliente()
                 {
                     Nome = clientesDados [0],
                     Email = clientesDados [1],
                     Cidade = clientesDados [2],
                     Pais = clientesDados [3],
                 })
        where c.Pais == "USA"
        select c;

A vantagem em usar o LINQ é a flexibilidade e o poder em realizar as consultas. Podemos por exemplo selecionar clientes que tenham a palavra net contida no email:

var consulta =
             from c in
            (from linha in File.ReadAllLines(caminhoArquivo)
             let clientesDados = linha.Split(',')
             select new Cliente()
                 {
                     Nome = clientesDados [0],
                     Email = clientesDados [1],
                     Cidade = clientesDados [2],
                     Pais = clientesDados [3],
                 })
        where c.Email.Contains("net")
        select c;

Vamos criar uma aplicação Windows Forms no SharpDevelop 3.0 para mostrar o exemplo funcionando:

Nota: Podemos usar também o Visual C# 2008 Express Edition.

No menu Arquivo selecione Novo -> Solução e a seguir selecione as opções C# -> Aplicações Windows e em Modelos Aplicação Windows informando o nome LerArquivoTexto. Para criar o projeto clique no botão Criar;

Declare a utilização dos namespaces abaixo:

using System.Linq;
using System.IO;

Declare no início do formulário a variável para conter o nome e caminho do arquivo texto:

string caminhoArquivo = "C:\\dados\\Clientes.txt";

A seguir defina o seguinte leiaute no formulário padrão form1.cs:

No menu Projeto -> Adicionar Novo Item selecione o item Classe, informe o nome Cliente.cs para criar a classe Cliente.

Agora basta colocar no evento Click de cada um dos botões o código correspondente. A seguir vemos o código completo de cada botão:

1- Botão Ler Arquivo Texto :

void BtnLerClick(object sender, EventArgs e)
{
	 try
	 {
	  var consulta =
             from linha in File.ReadAllLines(caminhoArquivo)
             let clienteDados = linha.Split(',')
             select new Cliente()
             {
                 Nome = clienteDados[0],
                 Email = clienteDados[1],
                 Cidade = clienteDados[2],
                 Pais = clienteDados[3],
             };
		
	   foreach (var item in consulta)
	   {
		lstTexto.Items.Add(item.Nome +","+ item.Email + ","+ item.Cidade + ","+ item.Pais);
	   }
	}
	catch (Exception ex)
	{
		MessageBox.Show(" Erro : " + ex.Message);
	}
}

2- Botão Filtrar por Pais:

void Button1Click(object sender, EventArgs e)
{
	try
	{
	     var consulta =
                from c in
                (from linha in File.ReadAllLines(caminhoArquivo)
                 let clientesDados = linha.Split(',')
                 select new Cliente()
                 {
                     Nome = clientesDados [0],
                     Email = clientesDados [1],
                     Cidade = clientesDados [2],
                     Pais = clientesDados [3],
                 })
       	     where c.Pais == "USA"
       	     select c;
		lstTexto.Items.Add(" - - - - Filtro por Pais: - - - - -")					
	     foreach (var item in consulta)
	     {
		lstTexto.Items.Add(item.Nome +","+ item.Email + ","+ item.Cidade + ","+ item.Pais);
	     }
	}
	catch (Exception ex)
	{
		MessageBox.Show(" Erro : " + ex.Message);
	}
}

3- Botão Filtrar Email:

void Button2Click(object sender, EventArgs e)
{
 	try
               {
	      var consulta =
                        from c in
                       (from linha in File.ReadAllLines(caminhoArquivo)
                       let clientesDados = linha.Split(',')
                       select new Cliente()
                       {
                         Nome = clientesDados [0],
                         Email = clientesDados [1],
                         Cidade = clientesDados [2],
                         Pais = clientesDados [3],
                       })
	        where c.Email.Contains("net")
        	       select c;
			lstTexto.Items.Add(" - - - - Filtro por Email: - - - - -")	
			foreach (var item in consulta)
			{
				lstTexto.Items.Add(item.Nome +","+ item.Email + ","+ item.Cidade + ","+ item.Pais);
			}
	}
               catch (Exception ex)
	{
		MessageBox.Show(" Erro : " + ex.Message);
	}
}

Executando o projeto e clicando em cada um dos botões iremos obter:

Você pode fazer o que quiser com os dados lidos. Salvar em um banco de dados, em um arquivo texto, etc...

Aguarde mais artigos sobre LINQ e pegue o projeto completo aqui: LerArquivoTexto.zip

Eu sei é apenas C# e LINQ, mas eu gosto...

Referências:


José Carlos Macoratti