I need to validate a TXT layout in C#

Asked

Viewed 763 times

4

I have a TXT file where I need to validate the number of characters of each column according to the layout of each document.

Note: Documents are all in one file *.txt

In the second column is the document type "0000,0400,0430". Each document has a different layout that has to be checked.

Layout documento 0000
Coluna 1 = 6 caracteres obrigatórios
Coluna 2 = 4 caracteres obrigatórios
Coluna 3 = 8 caracteres obrigatórios
Coluna 4 <= 100 caracteres maximo
Coluna 5 = 1 caracteres obrigatórios
Coluna 6 = 7 caracteres obrigatórios
Coluna 11 = 1 caractere ou vazio

000001|0000|00000000|ABCDFG|U|1234567|201601|201601|2|1||1|123456|1.0|1
000002|0400|123456|1|123456|2|ABCDFG|123456|1234567|1||
000003|0430|123456|1010101111|111000001|0,00|0,00|0,00|0,00||0,00|5,00|0,00|||

I have that code

class Program
{
    static void Main(string[] args)
    {
        string caminhoArquivo = "C:\\Temp\\Teste.txt";

        try
        {
              var consulta =
              from linha in File.ReadAllLines(caminhoArquivo)
              let clienteDados = linha.Split('|')
              where clienteDados[1] == "0000"
              select new Cliente()
              {
                  Num_Linha = clienteDados[0],
                  Reg = clienteDados[1],
                  CNPJ = clienteDados[2],
                  Nome = clienteDados[3],
              };

            foreach (var item in consulta)
            {               
                Console.WriteLine(item.Num_Linha + "|" + item.Reg + "|" + item.CNPJ + "|" + item.Nome + "|");
                Console.WriteLine(item.Num_Linha.Length == 6);
                Console.WriteLine(item.Reg.Length == 4);
                Console.WriteLine(item.CNPJ.Length == 8);
                Console.WriteLine(item.Nome.Length <= 100);
                Console.WriteLine(item.Reg);
                Console.ReadKey();
            }
        }
        catch (Exception ex)
        {

            Console.WriteLine(" Erro : " + ex.Message);
        }
    }

}

Customer.class

public class Cliente
  {       
    public string CNPJ { get; set; }
    public string Nome { get; set; }
    public string Num_Linha { get; set; }
    public string Reg { get; set; }
}
  • You just want to validate or use the file?

  • Just do the validation.

  • @Britto, this file seems to be from SPED, am I right? If yes I have a code that can help you.

  • Yes @Robss70 I need a help on this

  • Do you need to validate all the records or just a few? Because if you are going to validate all before importing you will have to have a class with all kinds of records and this is an absurd job. Before importing the file, it is usually only valid the record |0000| and the total count of record lines |9999|. After imported you only treat the registration that interests you. But I will post an example and see if it helps you.

3 answers

3

The way is to use the Nuget Filehelpers package. It is a tool that handles these types of files, although the lines are different.

How the lines are different according to the 2nd column, is a case of multiregistrations and the solution can take a little work.

My suggestion is that you create a class for each document type:

[DelimitedRecord("|")]
public class Registro0000
{
    public string NumeroLinha;
    public string TipoDocumento;
    public string Campo1;
    public string Campo2;
    public string Campo3;
    ...
}

[DelimitedRecord("|")]
public class Registro0400
{
    public string NumeroLinha;
    public string TipoDocumento;
    public string Campo1;
    public string Campo2;
    public string Campo3;
    ...
}

// Escreva os demais seguindo mais ou menos este padrão.

When reading this file, you will need to instantiate a:

var engine = new MultiRecordEngine(typeof (Registro0000),
    typeof (Registro0400),
    typeof (Registro0430), /* Coloque aqui as demais classes */);

engine.RecordSelector = new RecordTypeSelector(CustomSelector);

var resultado = engine.ReadFile("SeuArquivo.txt");

foreach (var registro in resultado)
    Console.WriteLine(registro.ToString());

Finally, write the record picker:

private Type CustomSelector(MultiRecordEngine engine, string recordLine)
{
    if (recordLine.Length == 0)
        return null;

    switch (recordLine.Substring(7, 10)) 
    {
        case "0000":
            return typeof (Registro0000);
        case "0400":
            return typeof (Registro0400);
        case "0430":
            return typeof (Registro0430);
    }

    return null;
}
  • I had already seen this tool, for what I am doing does not serve very well, but thank you very much for the tip.

  • Why not? You take resultado of the tool and applies its validation logic.

  • I’ve already got what Filehelpers does.

  • So update your question with what you have ready, please.

  • Without a sample of the code it is impossible to point out an answer.

  • Please update your question. Do not comment on the answer with code.

Show 1 more comment

2

@Britto, in an analogous situation, I used awk/gawk, with enough versatility. I know that the solution I point out does not meet the conditions you refer to, yet I think it might be useful.

#!/usr/bin/gawk -f
BEGIN{ FS="[|]"}

 $2 == "0000"  &&   v0000() { print "ok"; next }
 $2 == "0400"  &&   v0400() { print "ok"; next }
 $2 == "0430"  &&   v0430() { print "ok"; next }
                              { print NR ": invalid " $2 " record"; next }

function v0000(){               ## valida registos 0000
  return( length($1)==6   &&
          length($2)==4   &&
          length($4)<=100 &&
          length($11)<=1 )
}

function v0400(){               ## sem restrições
  return 1
}

function v0430(){
  return( length($1)==6   &&
          length($2)==4   &&
          $4 ~ /^[01]+$/ )      ## $4 contem apenas seq de "0" e "1"
}

(gawk is a tiny tool that runs on any operating system)

  • NR - registration number (line number)
  • FS - field separator

2

@Britto there are many ways to validate the txt file that Voce mentions, this one here is one of them, it’s ugly but it’s working, I delete some parts to reduce the size.

The method reads the file to the end, so you can put as many records as you want, for example if (xxxxxxxx.StartsWith("|xxxx|")) and go making the validations you need.

In this part _reg0000 = reg0000.Split(delimitador, StringSplitOptions.None); he will play in the array string[] _reg0000; and according to the size you compare with the amount of columns |0000| should have.

public void valida(string path_txt)
    {
        StringReader streamReader = new StringReader(path_txt);

        string reg0000;

        string[] _reg0000;

        char[] delimitador = new char[] { '|' };

        while ((reg0000 = streamReader.ReadLine()) != null)
        {
            if (reg0000.StartsWith("|0000|"))
            {
                try
                {
                    _reg0000 = reg0000.Split(delimitador, StringSplitOptions.None);

                    // 
                    //faça aqui as validações que achar preciso, por exemplo a quantidade de colunas.
                    //
                    //
                    //
                    //

                }
                catch (Exception ex)
                {

                    throw ex;
                }
            }
        }
    }

Browser other questions tagged

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