GARANTIR DESCONTO

Fórum Contagem de Linha (arquivo TXT) #182506

17/09/2003

0

Alguem sabe se existe uma função pronta no Delphi que retorne o número de linhas de um arquivo texto ??
No caso é um arquivo log do sistema... e quero inserir o número de cada registro, ou seja, inserir o numero 1 na primeira linha e ir incrementando a cada registro.
Uso o codigo abaixo para inserir as linhas...

--------------------------------------------
procedure RegistraLog (msg:string);
var f : textfile;
sr : TSearchRec;
begin
AssignFile (f, ´arquivo.log´);
if FindFirst (´arquivo.log´, faAnyFile, sr) = 0 then
begin
{$I-}
Reset (f);
{$I+}
IOResult;
end else
ReWrite (f);

Append (f);
WriteLn (f, DateTimeToStr (now), ´ ´, msg); // coloca a data e hora atual com a mensagem do registro na frente.
CloseFile (f);
end;
-----------------------------------------------------

Então preciso de um jeito para saber qual o número de linhas do arquivo para incrementar esse valor e colocar na proxima linha.

Agradeço a atenção,
Renato Mendes


Renato_mendes

Renato_mendes

Responder

Posts

17/09/2003

Bacalhau

Creio que não há essa função no Delphi. Uma alternativa é esta:

procedure RegistraLog (msg:string);

var f : textfile;
sr : TSearchRec;
i : integer; // adicionei esta variável

begin

i := 0; // inicializo

AssignFile (f, ´arquivo.log´);
Reset (f);

while not eof(f) do
begin
readln(f);
i := i + 1; // conto aqui o numero de linhas
end;

i := i + 1; // incremento o total de linhas lidas

closefile(f);
Append (f);
WriteLn (f, inttostr(i),DateTimeToStr (now), ´ ´, msg); // coloca valor de i
CloseFile (f);
end;


Abraço
bacalhau


Responder

Gostei + 0

18/09/2003

Renato_mendes

Valeu bacalhau...

Havia pensado em fazer uma rotina desse tipo para a contagem de linhas... só que achei que o pocessamento poderia ficar meio pesado, sendo que o arquivo vai crescendo e pode conter milhares de linhas... além de que em certos horários essa função pode ser executada várias vezes por segundo.
De qq jeito vou usar a tua ideia e ver como o sistema se comporta!!

Abraço,
Renato Mendes


Responder

Gostei + 0

18/09/2003

Wbb

Renato, há a possibilidade de fazer uma ´adaptação técnica´ (pra não dizer gambiarra...).

Insira no form um controle Memo e faça o seguinte:

Memo1.Lines.LoadFromFile(´C:\Temp\Arquivo.Log´);
Edit1.Text := IntToStr(Memo1.Lines.Count);


Eu tentei criar uma variável do tipo TMemo, apenas para não ter que colocar o Memo no form e deixá-lo invisível, porém dá um erro que não sei resolver. Caso você tente criar a variável também e resolva o erro, me diga como.

Ok?

Até mais.
wbb


Responder

Gostei + 0

18/09/2003

Bacalhau

Renato, de facto fica um pouco pesado, sobretudo se for várias vezes dentro do mesmo segundo (para não falar em possíveis colisões).

O wbb parece ter uma solução mais elegante. Se ele disser qual é o erro, talvez se possa dar uma solução diferente. Wbb, qual é o erro?


Responder

Gostei + 0

19/09/2003

Wbb

Beleza! Então vamos por partes...

Só lembrando que o problema acontece apenas quando eu tento executar o programa utilizando de uma variável do tipo TMemo. Quando eu coloco um controle Memo fisicamente no Form, não dá problema algum.

1º) Criei uma variável do tipo TMemo: [b:1c7a991ed8]Var Arquivo: TMemo;[/b:1c7a991ed8];
2º) Criei um arquivo texto contendo 8 linhas em: [b:1c7a991ed8]C:\Temp\testeA.txt[/b:1c7a991ed8];
3º) Criei o código no evento OnClick de um Button:

procedure TForm1.Button1Click(Sender: TObject);
Var Arquivo: TMemo;
begin
   Arquivo.Lines.LoadFromFile(´C:\Temp\testeA.txt´);
   Edit1.Text := IntToStr(Arquivo.Lines.Count);
end;


4º) Rodando o programa e clicando no botão, aparece imediatamente, logo na primeira linha, a seguinte mensagem:

[b:1c7a991ed8]Project Project1.exe raised exception class EAccessViolation with message ´Access violation at address 0044F04E in module ´Project1.exe´. Read of address 84FFFDAF´. Process stopped. Use Step or Run to continue.[/b:1c7a991ed8]

Não faço a menor idéia do que seja...

Dê uma forcinha aí Bacalhau! É certo que funciona do jeito que expliquei antes (com um Memo), mas nada melhor do que fazer as coisas certinhas...


Até mais.
wbb


Responder

Gostei + 0

19/09/2003

Ljr

O erro foi causado por que TMemo é um componente visual e para usá-lo vc dever inicia-lo antes.

Pensando em otimizacao, usei este codigo e da certo. Pois vc usa somente a propriedade LINES, entao usei uma variavel do mesmo tipo, portanto ficara mais leve.

var
f: TStringList;
begin
f:= TStringList.Create;
f.LoadFromFile(´C:\Temp\testeA.txt´);
Edit1.Text := IntToStr(f.Count);
end;

Espero ter ajudado


Responder

Gostei + 0

19/09/2003

Wbb

Ajudou sim. E muito, pois o que eu chamava de ´adaptação técnica´ (ou gambiarra, no verdadeiro sentido.. hehehe), agora posso chamar de técnica realmente.

Eu havia tentado usar um TStringList também, mas o mesmo erro ocorria. Agora, resolvido então.

Valeu!
wbb


Responder

Gostei + 0

19/09/2003

Ljr

Continuando...

Se vc quiser usar uma variavel do TMemo, use o codigo a seguir:

var
f: TMemo;
begin
f:= TMemo.Create(Self);
f.Visible:= False;
f.Parent:= Form1;
f.Lines.LoadFromFile(´c:\windows\desktop\ss.txt´);
caption:= IntToStr(f.Lines.Count);
f.Free;
end;


Note que eu Atribui False para a propriedade VISIBLE, caso feito o contrario vc podera visualisar o componente no formulario.

Usei o metodo FREE, para retira-lo da memoria.

espero ter ajudado


Responder

Gostei + 0

19/09/2003

Bacalhau

wbb eu fiz assim e deu

procedure TForm1.NumeroDeLinhas(Sender: TObject);

var arquivo : TMemo;
linhas : integer;

begin
arquivo := TMemo.create(arquivo);
arquivo.Parent := form1;
Arquivo.Lines.LoadFromFile(´teste.txt´);
linhas := Arquivo.Lines.Count;
arquivo.free;
end;


Responder

Gostei + 0

19/09/2003

Marcelo Saviski

Meu!, que chuncho que vocês estão fazendo,
vamos ajeitar isso:

se você quer retornar quantas linhas tem no arquivo, provavelmente a 1º função que o bacalhau passou vai ser mas rápida do que ficar usando um Memo, que foi projetado para outra coisa

essa função abaixo, foi retiradas das 800 dicas da LhoydSoft

function NumLinhasArq(Arqtexto:String): integer;
// Retorna o número de linhas que um arquivo possui
Var
  f: Textfile;
  linha, cont:integer;
Begin
linha := 0;
cont := 0;
AssignFile(f,Arqtexto);
Reset(f);
While not eof(f) Do
  begin
  ReadLn(f);
  Cont := Cont + 1;
  end;
Closefile(f);
result := cont;
end;



mas se por algum motivo vc´s não quiserem usar ela,
ou quiserem usar TStrings, façam assim:

var
  Arquivo : TStrings;
begin
  Arquivo := TStringList.Create(self); //Instancia o objeto
  try
    Arquivo.LoadFromFile(´ArquivoTal.log´);
    Quantidade_de_Linhas := Arquivo.Count;
  finally //Garante que o objeto vai ser liberado
   Arquivo.Free;
  end;
end;


e vc também não presisa ficar chamando ela várias vezes por segundo, crie uma variável para receber o resultado da função, assim, toda vez que presisar saber o nº de linhas do arquivo, pega o valor da variável,
e toda vez que alterar o arquivo, repita a operação


Responder

Gostei + 0

19/09/2003

Wbb

Para Bacalhau e/ou Marcelo Saviski: Qual a necessidade de usar [b:6781c6d73c]Free [/b:6781c6d73c]ao final da rotina, considerando que a variável ´Arquivo´ foi criada como sendo local? Ao término de execução da rotina a variável não será destruida automaticamente?

E, para o Marcelo Saviski, uma curiosidade minha: Como faço para que a rotina da [i:6781c6d73c][b:6781c6d73c]function NumLinhasArq(Arqtexto:String): integer;[/b:6781c6d73c][/i:6781c6d73c] que você indicou, seja mais rápida para determinar o número de linhas do arquivo, do que da forma com TStringList? Pergunto isso, pois fiz testes com arquivos grandes, sendo apresentada mais rápida a resposta com TStringList.


Grato!
wbb


Responder

Gostei + 0

19/09/2003

Marcelo Saviski

Bom, eu ´chutei´ que a função seria mas rápida do que com StringList,
não fiz nenhum teste para saber ao certo, mas se com StringList é mais Agil, vamos de StringList então 8)

e sobre o Arquivo.Free;

em todas as funções que eu vi, é feito assim.
acho que Arquivo não é liberada ao final da Rotina.
e assim fica mais seguro

estou sem o Delphi para poder testar, mas se vc puder, tenta isso:

function ObjetoDestruidoAoFimDaRotina : boolean;
var
  s : TStrings;
begin
  if not Assign(s) then
   begin
    s := TStringLis.Create(self);
    result := true;
   end
  else
    Result := false;
end;

e chame assim, em algum Button:

ObjetoDestruidoAoFimDaRotina;// chama ela 1 vez para que crie o Objeto
if ObjetoDestruidoAoFimDaRotina  then ShowMessage(´O Objeto não foi destruido na última vez que a função foi chamada´);


é só um teste para tirar essa dúvida

Pelo o que eu sabia, era que Strings, Arrays, Variants,... são Liberados automaticamente, quanto aos outros, não sei

se vc puder, faça o teste e diga o que aconteceu

vlw


Responder

Gostei + 0

20/09/2003

Bacalhau

PESSOAL, ESTAMOS A ARRANJAR UM PROBLEMA PARA CADA SOLUÇÃO :lol: :lol:

O que fiz foi:

criei o TMemo (create)
executei o que queria
libertei o TMemo da memória (free). pq já não preciso dele

Para o caso de queremos aceder várias vezes por segundo, o melhor é criar o TMemo como variavel global, fazer o Create na propriedade FormCreate e destruí-lo em OnClose.

E já que estamos numa de enriquecer este tópico :lol: sugiro fazermos um teste.

Criamos duas variáveis Time_ini e Time_fim do tipo TDateTime. Antes de iniciar a operação capturamos a hora que começou e no fim capturamos a hora que terminou. Isto determina o tempo gasto na operação.

Depois criamos um txt com 10000 linhas (ou mais...) e executamos a minha rotina inicial, depois com o TMemo e depois com o StringList.

A que der um tempo mais baixo é declarada vencedora e o Renato vai usá-la :lol:

Abraço com as barbatanas do peixão norueguês


Responder

Gostei + 0

20/09/2003

Mandachuva

PESSOAL, ESTAMOS A ARRANJAR UM PROBLEMA PARA CADA SOLUÇÃO :lol: :lol: O que fiz foi: criei o TMemo (create) executei o que queria libertei o TMemo da memória (free). pq já não preciso dele Para o caso de queremos aceder várias vezes por segundo, o melhor é criar o TMemo como variavel global, fazer o Create na propriedade FormCreate e destruí-lo em OnClose. E já que estamos numa de enriquecer este tópico :lol: sugiro fazermos um teste. Criamos duas variáveis Time_ini e Time_fim do tipo TDateTime. Antes de iniciar a operação capturamos a hora que começou e no fim capturamos a hora que terminou. Isto determina o tempo gasto na operação. Depois criamos um txt com 10000 linhas (ou mais...) e executamos a minha rotina inicial, depois com o TMemo e depois com o StringList. A que der um tempo mais baixo é declarada vencedora e o Renato vai usá-la :lol: Abraço com as barbatanas do peixão norueguês


OLha, isso que eu chamo de enjambração, ou melhor, gambiarra. Usar TMemo pra contar linhas de arquivos? Se por um lado, a contagem de linhas via WHILE NOT EOF()..READLN() é lenta, por outro lado, via TMemo, não há dierença alguma, pois o mesmo terá que carregar todo o arquivo na memória. E se o arquivo for gigante? Haja memória hein!
Usando TStringList ou usando as funções ´puras´ do pascal seria a forma mais profissional de fazer isso.
Tchau.


Responder

Gostei + 0

20/09/2003

Wbb

hehehehehehehehehehehe.......

Apelou heim Bacalhau!!! hahahahahahahaha......

Acho que Renato já até resolveu o problema dele e nós estamos aqui ainda... Também, nada melhor do fazermos o que gostamos e ainda dar umas risadas...


Até mais!
:lol:
wbb


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar