Comparar e deletar linhas duplicadas em TXT

Delphi

11/07/2008

Bom Dia Galera,

Fiz um programinha em delphi para substituir pipe | por ;
Ainda irei melhorar o programinha, mas irei postar aki p vocês caso alguém precise:

Function TForm1.GravaTxt(Texto : String; Destino : String) : String;
var
  arq: TextFile;
  linha: String;
begin

  AssignFile ( arq, Destino );

  If not(fileexists(Destino)) then
    Rewrite (arq )  // Apaga o Arq
  Else
    Append ( arq );     // Sobre escreve o Arq

  Writeln ( arq, Texto );     // Escreve

  CloseFile ( arq );


end;

Function TForm1.VerificaCMD(Texto : String) : String;
Begin
  If ( UpperCase(Texto) = ´$P´) Then  // O DOS não reconhece o caracter | (pipe)
    Result := ´|´                    //  portanto tive que criar um IF para sua identificação
  else
    Result := Texto;
End;


procedure TForm1.FormCreate(Sender: TObject);
var
  C : Integer;
  arq: TextFile;
  linha, nomeDoArquivo: String;
begin

  If (ParamCount <= 4) then
  Begin

    nomeDoArquivo :=  ParamStr(1);

    AssignFile ( arq, nomeDoArquivo  );

    Reset(arq);

    While not eof(arq) do
    Begin

      ReadLn ( arq, linha ); // Le.. // linha Atual pulando a linha

      linha := StringReplace(Linha, VerificaCMD(ParamStr(3))  , ParamStr(4) ,[rfReplaceAll]);

     if (linha == linha) them

      GravaTxt(Linha, ParamStr(2) );
     end;
    End;

    CloseFile ( arq );

    Close;
  End
  Else
    ShowMessage(´Somente é permitido no maximo 4 parametros!´);



  ExitProcess(0);


end;




end.



Uma das opções que preciso fazer neste programa, é ele ler todos os registros de um arquivo TXT e deletar o registro duplicado, exemplo:

[list:74d1c6a9e2]

João batista; 1; 2008
João batista; 1; 2008
José da Silva;2;2007
José da Silva;3;2008
Luciano Gomes;5;2001
Luciano Gomes;5;2001[/list:u:74d1c6a9e2]

O arquivo deverá ficar:

[list:74d1c6a9e2]
João batista; 1; 2008
José da Silva;2;2007
José da Silva;3;2008
Luciano Gomes;5;2001
[/list:u:74d1c6a9e2]


Shion86

Shion86

Curtidas 0

Respostas

Paulo

Paulo

11/07/2008

É possível que haja muitas formas de se fazer. No momento eu iria lendo linha-a-linha e guardando num variável. Se a próxima linha for identica ao conteúdo da variável eu deleto essa linha. Mas isso tem um problema; só vale para linhas repetidas imediatamente após a outra. Caso se repita em linhas alternadas, aí seria de outra forma. Mas como vi o seu exemplo, imediatamente após a outra, eu faria assim. Isto é só um entre muitas formas. Logo vc terá aqui nesse forum outras opções.


GOSTEI 0
Shion86

Shion86

11/07/2008

Valeu Paulo,
Estou pensando em fazer um for após ele ler o registro e excluir o dado, o grande problema é q eu estava utilizando .NET e me jogaram esse probleminha em delphi :shock:
mas obrigado pela ajuda, vou me esforçar aki p solucionar isso, já que preciso entregar hoje :cry:


GOSTEI 0
Fabianosales

Fabianosales

11/07/2008

Uma maneira bem simples de conseguir isto, Shion86, é utilizar uma instância de TStringList configurada para ignorar duplicidades.
Seu código ficaria asism:
var
  sl : TStringList;
  Origem, Destino, linha : string;
  f : TextFile;
begin
  Origem  := ´c:\temp\origem.txt´;
  Destino := ´c:\temp\destino.txt´;
  sl := TStringList.Create;

  //dupIgnore (Ignora as tentativas de adicionar itens duplicados à lista)
  sl.Duplicates := dupIgnore;
  try
    AssignFile(f, Origem);
    Reset(f);
    while not(Eof(f)) do
      begin
        Readln(f, linha);
        linha := StringReplace(StringReplace(linha, ´$P´, ´|´, [rfReplaceAll]), ´|´, ´;´, [rfReplaceAll]);
        sl.Add(linha);
      end;
  finally
    CloseFile(f);
  end;
  sl.SaveToFile(Destino);
  FreeAndNil(sl);
end;


Veja que a TStringList encapsula os algoritmos de busca e ordenação necessários para completar essa tarefa da maneira mais simples possível.


GOSTEI 0
Marco Salles

Marco Salles

11/07/2008

acho que num precisa percorrer linha por linha de TStringList

Acho que so isso resolve

Lista:=TstringList.create;
Lista.LoadFromFile(caminho);
lista.Text:=stringReplace(lista.Text,´|´, ´;´, [rfReplaceAll]);
lista.SaveToFile(caminho);
lista.free;



GOSTEI 0
Shion86

Shion86

11/07/2008

Valeu a ajuda galera, vou testar da forma que vocês postaram, mas fiz assim:

while not Eof(txtORIGINAL) do
     begin

          ReadLn(txtORIGINAL, sBufferOrig);

          sBufferOrig := TROCA_CARAC_BRANCO(sBufferOrig);

          if (sBufferOrig <> sBufferOrig_2) then
          begin
             {grava arquivo de saida}
              WriteLn(txtSAIDA, sBufferOrig);
          end;

          sBufferOrig_2 :=  sBufferOrig;

     end;


O código acima, irá comparar as linhas em sequencia, se forem iguais ele nao irá adicionar a ´repetida´, o único problema é que funciona apenas se os registros forem sequencias, agora se tiver assim:

joao
francisco
joao
mario
carlos

ele continuará gravando o joao novamente =/


GOSTEI 0
Paulo

Paulo

11/07/2008

Viu como vc teve várias respostas? Esse forum é assim, basta perguntar. Agora quanto a sua dúvida caso as linhas não sejam sequenciais, aí eu usaria o exemplo do fabianosales.


GOSTEI 0
Aroldo Zanela

Aroldo Zanela

11/07/2008

Colega,

Para diversão, existem várias formas de se implementar isso. Entretanto, conforme já foi citado, o uso de instâncias da classe TStringList é a forma de menor esforço.

var
  Origem, Destino: TStringList;
  I, N: Integer;
begin
  Origem              := TStringList.Create;
  Destino             := TStringList.Create;
  // Note:Duplicates does nothing if the list is not sorted.
  Destino.Sorted      := True;
  Destino.Duplicates  := dupIgnore;

  Origem.LoadFromFile(´D:\JOB\Shion86\origem.txt´);

  N := Origem.Count-1;

  for I := 0 to N do
     Destino.Add(StringReplace(Origem.Strings[I], ´|´, ´;´, [rfReplaceAll]));

  Destino.SaveToFile(´D:\JOB\Shion86\destino.txt´);

  FreeAndNil(Origem);
  FreeAndNil(Destino);
end;



GOSTEI 0
Shion86

Shion86

11/07/2008

Valeuu a forçaaa galera!
Obrigado a todos mesmo..


GOSTEI 0
Marco Salles

Marco Salles

11/07/2008

eu ainda continuo achando que não é necessário percorrer toda a Tstring

for I := 0 to N do Destino.Add(StringReplace(Origem.Strings[I], ´|´, ´;´, [rfReplaceAll]))


por:
Destino.Text:=stringReplace(Origem.Text,´|´, ´;´, [rfReplaceAll]);


não funciona ??????


GOSTEI 0
Aroldo Zanela

Aroldo Zanela

11/07/2008

Olá Marco,

Perfeito, você tem razão e podemos simplificar ainda mais:

var
  Arquivo: TStringList;
begin
  Arquivo              := TStringList.Create;
  // Note:   Duplicates does nothing if the list is not sorted.
  Arquivo.Sorted      := True;
  Arquivo.Duplicates  := dupIgnore;

  Arquivo.LoadFromFile(´D:\JOB\Shion86\Arquivo_texto.txt´);
  Arquivo.Text := StringReplace(Arquivo.Text, ´|´, ´;´, [rfReplaceAll]);
  Arquivo.SaveToFile(´D:\JOB\Shion86\Arquivo_texto.txt´);

  FreeAndNil(Arquivo);
end;



GOSTEI 0
Wdrocha

Wdrocha

11/07/2008

Oi Zanela e Marcos...


Estou acompanhando o tópico, pois achei interassante...e venho testando as soluções d vcs...


Tow aprendendo mt aq com vcs...



Vlw...


GOSTEI 0
POSTAR