Hoje vou falar de uma biblioteca free, muito legal  pois irá facilitar muito a vida dos programadores.

Quem hoje nunca precisou ler um arquivo ou escrever em um txt ou Excel e teve que fazer tudo isso na mão?

Bom, existe uma biblioteca chamada filehelpers de código aberto que faz todo esse serviço pesado para nós, para baixar é só acessar o site filehelpers

Para que a leitura dos arquivos funcione, devemos fazer referência a dll FileHelpers.

 

Então vamos aos exemplos:

Vamos começar com um exemplo simples, ler um arquivo txt com o delimitador vírgula ( “,”).

Estrutura do arquivo que será lido:

img
Primeiro, precisamos criar a classe que irá dizer como eu vou ler esse arquivo e em quais campos irei colocar as informações.

//Operador que informa que essa classe irá ler o arquivo com um delimitador

[DelimitedRecord(",")]

public class Pessoa

{

public string Nome;

      public string Endereco;

      //O atributo FieldConverter converte o seu dado para um tipo especifico, neste caso para date

      [FieldConverter(ConverterKind.Date, "dd/MM/yyyy")]

      public DateTime Data;

}

Fazendo a chamada em um método qualquer.

//declarando a variavel que ira ler o arquivo e passando o tipo da classe que ira ler os dados

FileHelperEngine file = new FileHelperEngine(typeof(Pessoa), System.Text.Encoding.UTF8);

 

// Seu retorno será um array da classe do tipo informado acima, fazendo sua conversão                        

Pessoa[] retorno = file.ReadFile("teste.txt") as Pessoa[];

 

//com os dados preencidos na classe pessoa, é só ler os dados           

foreach (Pessoa item in retorno)

{

 MessageBox.Show(string.Format("Nome: {0} Endereço: {1} Data: {2}", item.Nome, item.Endereco, item.Data));

}

Vamos fazer outro exemplo, agora com os campos fixo sem delimitador.

Estrutura do arquivo que será lido:

 
img

Primeiro a classe que irá dizer como eu vou ler esse arquivo e quais campos eu irei colocar as informações.

//Operador que informa que essa classe ira ler o aquivo com a posição fixa

[FixedLengthRecord()]

public class PessoaFixo

{

     [FieldFixedLength(4)]

      public int cd;

 

     [FieldFixedLength(10)]

      public string Nome;

 

     [FieldFixedLength(11)]

      public string Documento;

 

     [FieldFixedLength(3)]

      public decimal Valor;

}

 

Fazendo a chamada em um método qualquer:

FileHelperEngine engine = new FileHelperEngine(typeof(PessoaFixo), System.Text.Encoding.UTF8);

 

PessoaFixo[] res = engine.ReadFile("_teste.txt") as PessoaFixo[];

 

foreach (PessoaFixo item in res)

{

MessageBox.Show(string.Format("cd: {0} Nome: {1} Documento: {2}} ", item.cd, item.Nome, item.Documento));

}

Veja que a leitura do arquivo com tamanho fixo foi o mesmo que no arquivo com delimitador, apenas na classe que irá receber os dados foi feito de forma diferente, qualquer mudança de layout basta alterar o arquivo responsável para armazenar os dados.

E se eu precisar manusear os dados quando estiver lendo ou escrevendo os arquivos, é possível? Sim, é possível. É só sobrescrever a classe base de leitura e escrita e informar qual campo irá usar essa classe base, vamos ao exemplo: 

[FixedLengthRecord()]

 public class PessoaFixo

 {

      [FieldFixedLength(4)]

       public int cd;

 

      [FieldFixedLength(10)]

       public string Nome;

 

      [FieldFixedLength(11)]

       public string Documento;

 

      [FieldFixedLength(3)] 

      [FieldConverter(typeof(DecimalConverter))]

      public decimal Valor;

 

      internal class DecimalConverter : ConverterBase

      {

          ///

          /// executa na hora de ler o arquivo

          ///

          ///

          ///

          public override object StringToField(string from)

          {

               decimal retorno = Convert.ToDecimal(from);

               return retorno * 100;

           }

 

          ///

          /// executa na hora que estiver escrevendo no arquivo

          ///

          ///

          ///

           public override string FieldToString(object from)

           {

               decimal retorno = (decimal)from;

               return Math.Round(retorno - 100).ToString();

           }

       }

 

    }

 

Observe que foi incluída uma classe chamada DecimalConverter do tipo internal herdando da classe base ConverterBase e sendo sobrescrito dois métodos. StringToField que é executado quando o dado é lido do arquivo e outro metodo FieldToString que é executado quando o dado é escrito no arquivo, e na variável Valor da classe PessoaFixo possui dois atributos FieldFixedLength e FieldConverter.

O Atributo FieldFixedLength, informa o tamanho que o campo deverá ter, e está presente em todas as variáveis da classe e o FieldConverter, que recebe o tipo da classe que irá sobrescrever os métodos de leitura e escrita.

 

Note que o layout do arquivo está na própria classe, pois é nela que se informa o tamanho de cada campo, com isso o código fica mais limpo, mais estruturado, evitando o famoso POG e de fácil manutenção.

 

Vamos ver agora como lêr um arquivo do excel.

 

Para que a leitura do excel funcione, devemos fazer referencia da dll FileHelpers.ExcelStorage.

 

Estrutura do arquivo que será lido:

 img

 

Primeiro,  a classe que irá receber os dados:

 

[DelimitedRecord("|")]

public class Excel

{

      public string Campo1;

      public string Campo2;

      public string Campo3;

      public string Campo4;

}

 

 

Código para ser chamado em um método qualquer:

 

FileHelpers.DataLink.ExcelStorage provider = new FileHelpers.DataLink.ExcelStorage(typeof(Excel));

 

provider.StartRow = 3;

provider.StartColumn = 2;

 

provider.FileName = "teste.xls";

 

Excel[] ex = provider.ExtractRecords() as Excel[];

 

foreach (var item in ex)

{

MessageBox.Show(string.Format("Campo 1 {0} Campo 2 {1} Campo 3 {2} Campo 4 {3}", item.Campo1, item.Campo2, item.Campo3, item.Campo4));

}

 

Observe que declaramos um FileHelpers.DataLink.ExcelStorage que será responsável pela leitura do excel passando o tipo da classe que irá receber os dados.

As propriedades StartRow e StartColumn,são responsaveis por informar em que ceéula deverá ser iniciada a leitura do arquivo e a ordem dos campos da classe será a mesma ordem da planilha, isso serve para todos os arquivos.

Agora vamos ao nosso último exemplo, que é fazer um transferência de um arquivo com delimitador para um de tamanho fixo, e veremos que esse procedimento é muito simples.

[DelimitedRecord(",")]

public class FromPessoa

{

     public string Nome;

     public string Endereco;

 

     [FieldConverter(ConverterKind.Date, "dd/MM/yyyy")]

     public DateTime Data;

 

 

     [TransformToRecord(typeof(ToPessoa))]

     public ToPessoa Tranferir()

    {

          ToPessoa p = new ToPessoa();

          p.Nome = Nome;

          p.Endereco = Endereco;

          p.Data = Data;

 

          return p;

     }

}

[FixedLengthRecord()]

public class ToPessoa

{

    [FieldFixedLength(50)]

    public string Nome;

 

    [FieldFixedLength(50)]

    public string Endereco;

 

    [FieldFixedLength(10)]

    [FieldConverter(ConverterKind.Date, "dd/MM/yyyy")]

     public DateTime Data;

}

 

Foram criadas duas classe uma que será a origem da leitura que se chama FromPessoa e outra a destino chamada ToPessoa, na classe de origem FromPessoa foi criado um método do tipo ToPessoa da classe de destino com um atributo TransformToRecord que recebe o tipo da classe de destino ToPessoa, é este metodo o responsável por fazer a transferência dos dados. Na classe de destino uma configuração simples dos campos fixos.

 

Em um método qualquer fazer a chamada com o codigo abaixo:

 

FileTransformEngine transf = new FileTransformEngine(typeof(FromPessoa), typeof(ToPessoa));

 

transf.TransformFile("teste.txt", "teste_source.txt");

A classe FileTransformEngine é instânciada passando dois parâmetros no seu construtor, o tipo de origem que nesse caso é o FromPessoa e o tipo do destino que será o ToPessoa, depois chama-se o método TransformFile passando em qual arquivo esta a origem e em qual arquivo será o destino, veja abaixo o resultado.

 img

img

Veja que essa biblioteca facilita muito o trabalho dos desenvolvedores além de deixar o código mais enxuto, vai ai essa dica bacana.