Generate txt file according to the predefined layout in c#

Asked

Viewed 2,346 times

3

I need to export data from a class according to a specific layout consisting of size and position.

For easy maintenance, I need simple layout change.

Follow down my class:

    public class NovosCotistasDTO
    {
        public string Agencia { get; set; }
        public string Conta { get; set; }
        public DateTime DataInclusao { get; set; }
        public string Tipo { get; set; }
        public string IdUsuario { get; set; }
        public string CNPJ { get; set; }
    }  

Below follows Layout that must be exported:

Campo           |Tamanho    |Posição Inicial    |Posição Final
--------------------------------------------------------------
Agencia         |5          |1                  |5
Conta           |13         |6                  |19
DataInclusao    |10         |20                 |30
Tipo            |1          |31                 |32
IdUsuario       |7          |33                 |40
CNPJ            |14         |41                 |55
  • What you’ve already done?

2 answers

4

The library Filehelpers does exactly what you need.

With it you can set file layouts by size and position.

In your specific case, after importing the Filehelpers in your project, you would implement as follows:

Class Defining the Layout

Reply Edition: it is necessary to use simple fields instead of properties (get / set).

using FileHelpers;

[FixedLengthRecord(FixedMode.ExactLength)]
public class NovosCotistasDTO
{
    [FieldFixedLength(5)]
    public string agencia;

    [FieldFixedLength(13)]
    public string conta;

    [FieldFixedLength(10)]
    [FieldConverter(ConverterKind.Date, "ddMMyyyy")] // Outros formatos de data são possíveis. Ex: "DD/MM/AAAA", "ddMMyyyyHHmmss", etc.
    public DateTime dataInclusao;

    [FieldFixedLength(1)]
    public string tipo;

    [FieldFixedLength(7)]
    public string idUsuario;

    [FieldFixedLength(14)]
    public string cnpj;
} 

How to Save Records to TXT File

Writing a log file using Filehelpers is quite simple. You take a list of the objects you want to save to file and pass to Filehelpers as follows:

public void EscrevaArquivo(string nomeDoArquivo, List<object> registros)
{
    FileHelperEngine engine = new FileHelperEngine(typeof(NovosCotistasDTO));

    engine.WriteFile(nomeDoArquivo, registros);
}

How to Read Saved Records in File

To get back the records you saved using this layout, just do it as follows:

public List<NovosCotistasDTO> LeiaArquivo(string nomeDoArquivo)
{
    var engine = new FileHelperEngine(typeof(NovosCotistasDTO));

    var linhasDoArquivo = engine.ReadFile(nomeDoArquivo);

    var listaDeRegistros = new List<NovosCotistasDTO>();

    foreach (var linha in linhasDoArquivo)
    {
        lista.Add((NovosCotistasDTO)linha);
    }

    return listaDeRegistros;
}
  • Very cool this lib. +1.

  • I also like Filehelpers, @Ciganomorrisonmendez. I’ve updated the answer now by adding examples of how to read and how to write files using the layout. Any questions you might want to ask me. :)

  • Powder my like this guy, but it’s not working I checked that the attribute "Fieldfixedlength", can not be used with "get" and "set". When I am instantiating Multirecordengine(typeof(Novoscotistasdto)); error occurs "An unhandled Exception of type 'Filehelpers.Badusageexception' You only provide one type to the engine constructor. You need 2 or more types, for one type you can use the Filehelperengine."

  • I am trying to use Filehelperengine and it occurs the following error "Exception of type 'Filehelpers.Badusageexception' occurred in Filehelpers.dll The field: 'Agencia' can’t be marked with Fieldfixedlength attribute, it is only for the Lengthedrecords Fixnot for delimited ones.". Hang on, you know what I’m doing wrong ?

  • @Luãgovindamendessouza regarding the properties, really Filehelpers has this limitation. I will update the answer using simple fields instead of properties.

  • @Luãgovindamendessouza I think I found the reason for the mistake. The Multrecordengine serves for when there is more than one type of record, but as in your case there is only one type of record (Novoscotistasdto) so have to use the Filehelperengine in that case. I will modify the response by changing the engine statement to Filehelperengine engine = new Filehelperengine(typeof(Newotistasdto));. When you can, please take a test to check if it worked. Thank you.

  • @Ulyssesalves I made the change to "Filehelperengine" and returned the following error "An unhandled Exception of type 'Filehelpers.Badusageexception' occurred in Filehelpers.dll Additional information: The field: 'Agencia' can’t be marked with Fieldfixedlength attribute, it is only for the Lengthedrecords Fixnot for delimited ones." I could see in the documentation but where I am working I do not have access to the page of this Helper.

  • @Luãgovindamendessouza Please try to put the attribute [FixedLengthRecord(FixedMode.ExactLength)] on the definition of the record class in public class Novoscotistasdto. I updated the answer again with this change/correction.

Show 3 more comments

1

There are several ways to solve it. One of my favorites is to make a override of ToString():

public class NovosCotistasDTO
{
    public string Agencia { get; set; }
    public string Conta { get; set; }
    public DateTime DataInclusao { get; set; }
    public string Tipo { get; set; }
    public string IdUsuario { get; set; }
    public string CNPJ { get; set; }

    public override String ToString() 
    {
        return Agencia.Replace("-", "") + 
            Conta.Replace("-", "").Replace(".", "") +
            DataInclusao.ToString("dd/MM/yyyy") +
            Tipo.Substring(0, 30) +
            IdUsuario.Substring(0, 7) +
            CNPJ.Replace("-", "").Replace(".", "").Replace("/", "")
    }
}

Use:

var cotistaDto = new NovosCotistasDTO 
{
    Agencia = "1234",
    Conta = "12345-6",
    DataInclusao = DateTime.Now,
    Tipo = "Tipo",
    IdUsuario = "Usuario",
    CNPJ = "12.345.678/0001-99"
};

String layout = cotistaDto.ToString();

Note that this solution is quite simple, and the character control is entirely manual.

Using String.Format it is possible to do something even more sophisticated, but it is necessary to better understand how are your data conditions:

  • What happens when a die is bigger than the mask;
  • How data is assigned in your DTO;
  • Other validation conditions.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.