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:
//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:
//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:
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.
Veja que essa biblioteca facilita muito o trabalho dos desenvolvedores além de deixar o código mais enxuto, vai ai essa dica bacana.