Contagem de Linha (arquivo TXT)
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
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
Curtidas 0
Respostas
Bacalhau
17/09/2003
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
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
GOSTEI 0
Renato_mendes
17/09/2003
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
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
GOSTEI 0
Wbb
17/09/2003
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:
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
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
GOSTEI 0
Bacalhau
17/09/2003
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?
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?
GOSTEI 0
Wbb
17/09/2003
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:
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
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
GOSTEI 0
Ljr
17/09/2003
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
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
GOSTEI 0
Wbb
17/09/2003
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
Eu havia tentado usar um TStringList também, mas o mesmo erro ocorria. Agora, resolvido então.
Valeu!
wbb
GOSTEI 0
Ljr
17/09/2003
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
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
GOSTEI 0
Bacalhau
17/09/2003
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;
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;
GOSTEI 0
Marcelo Saviski
17/09/2003
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
mas se por algum motivo vc´s não quiserem usar ela,
ou quiserem usar TStrings, façam assim:
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
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
GOSTEI 0
Wbb
17/09/2003
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
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
GOSTEI 0
Marcelo Saviski
17/09/2003
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:
e chame assim, em algum Button:
é 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
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
GOSTEI 0
Bacalhau
17/09/2003
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
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
GOSTEI 0
Mandachuva
17/09/2003
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.
GOSTEI 0
Wbb
17/09/2003
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
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
GOSTEI 0
Bacalhau
17/09/2003
Manda chuva, não é gambiarra. É simplesmente testar com várias soluções e ver qual delas é mais eficaz a resolver o problema
GOSTEI 0