Página 1 de 1
Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 00:01
por lugab
Ola amigos,
Tenho um TXT com várias linhas de vários tamanhos, tal como essas do arquivo abaixo
"ARQUIVO.TXT"
123456ABCDZZ
123457ABXZZZ123.45
234567AAAAAA222.55ESCOLA PUBLICA
234668bbbbbbb
123458XXAAXX234.44ACADEMIA
...etc
Para ler cada uma dessas linhas em comando de baixo nível, eu preciso dar FOPEN() e vários FREAD(), isso até eu sei, o que eu não sei é como descobrir o tamanho de cada uma dessas linhas e é essa a ajuda que venho aqui pedir a vcs:
Mas antes de pedir-lhe ajuda, eu q não sou peguiçoso, consultei os vários tópicos aqui no fórum, mas todos os exemplos que achei só tratavam de arquvos com tamanho de linha fixa, de conhecimento prévio do programador, ou seja: não vi nenhum código para ler TXT com linhas de tamanho variável.
Pronto, é isso o q preciso aprender.
Grato a todos por qq ajuda.
Gabriel
Re: Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 02:11
por Maligno
Para resolver problema desse tipo você precisa pensar em um aspecto importante: a padronização que se pode encontrar, ou seja, o par CR/LF que separa as linhas, como se vê no padrão DOS. O alvo é um arquivo texto com mais de uma linha, e de tamanhos diferentes. Ou mesmo iguais. O comprimento das linhas não deveria fazer diferença alguma, pois uma boa solução contempla os dois casos.
A melhor solução que vejo para esse problema é fazer como eu próprio: usar um sub-sistema de tratamento de arquivos texto, que dá o conforto de ler as linhas sequencialmente ou uma determinada linha apenas com algumas poucas chamadas de funções. Nunca mais tive que perder tempo sequer pensando nisso.
Para resolver seu problema ofereço a você o sub-sistema que fiz e que acabei de subir para a seção de contribuições. Estude-o. Há uns conceitos interessantes nele. Além de conhecer outros recursos, além dos que exponho aqui.
Veja que, no modo bem básico, uma "varrida" sequencial do arquivo é bem simples:
Código: Selecionar todos
function LerTxtTst()
if !txOpen("arquivo.txt","ALIAS",_kTXTSYS_ACCESS_READ) = _kTXTSYS_NOERROR
// Um erro qualquer na abertura. Pode-se analisar o retorno da função.
return .F.
end
*
cLine := ""
for i := 1 to txLines()
txGetLine(@cLine,i)
//
// cLine contém a linha, sem o par CR/LF
// Processe-a do jeito que precisar.
next
txClose()
return (i>1) // o valor .F. sinaliza que o arquivo está vazio.
Dica: dedique uma especial atenção à função pré-leitora (quinto argumento de txOpen()), através da qual você poderá formatar a linha para que a função txGetLine() já a entregue formatada da maneira que você precisar.
Re: Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 08:08
por lugab
Maligno, obrigado, mas a minha qualificação técnica é muito incipiente pra compreender tão sofisticada solução. Sou um advogado q foi forçado a assumir a administração de um negócio familiar, que inclui dar manutenção em um sistema próprio de informática q era em clipper e q hj está alterado para incorporar os recursos do harbour.
Acho que o q mais preciso no momento é aprender a identificar o tamanho de cada uma das linhas.
Será que não seria através do comando AT() pra ver em que coluna da linha começa o chr(13)+chr(10) ?.
Se sim, como seria esse comando at() ?
Grato,
Gabriel
Re: Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 08:52
por Maligno
Se sua intenção é
aprender a identificar cada linha individualmente, o fonte do sistema que publiquei tem a resposta. Você deve se concentrar na função BuildIndex(). O que ela faz é (basicamente) identificar o terminador de linha CR/LF.
Para sua apreciação e aprendizado, eis um código simples, feito agora mesmo (sem testar), que vai direto à sua questão: separar as linhas individualmente. Para efeito didático não incluí qualquer checagem de erro. Se tiver dúvida é só voltar ao assunto.
Código: Selecionar todos
#define _kBUFFER_SIZE 4096
#define _kEOL Chr(13)+Chr(10)
*
function LerArquivo(cFName)
local nHand
local cBuff := Space(_kBUFFER_SIZE)
local cRead := ""
local cLine
local i
//
// Abertura do arquivo (checagens de erro serão ignoradas)
nHandle := FOpen(cFName)
//
// Leitura do arquivo sequencialmente
while (n := FRead(nHand,@cBuff,_kBUFFER_SIZE)) > 0
cRead += Left(cBuff,n)
while (i := At(_kEOL,cRead)) > 0
cLine := Left(cRead,i-1)
cBuff := SubStr(cRead,i+Len(_kEOL))
//
// -----------------------------------------------
// Nesse ponto você tem em cLine uma linha isolada
// -----------------------------------------------
//
end
cBuff := Space(_kBUFFER_SIZE)
end
*
if !Empty(cRead)
// Se em cRead restar algum texto significa que a última linha
// do arquivo não possui o terminador CR/LF. Pode acontecer.
end
FClose(nHand)
return nil
Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 10:16
por Pablo César
Só para corrigir e complementar...
consultei os vários tópicos aqui no fórum, mas todos os exemplos que achei só tratavam de arquvos com tamanho de linha fixa
Ficou faltando ver estes exemplos:
https://pctoledo.org/forum/viewto ... nha#p66652
https://pctoledo.org/forum/viewto ... PEN#p29317
Esses tópicos também tratam a leitura linha a linha de arquivos textos com tamanho de linha variável. Sei que tem mais uma exemplo, mas não achei...
Re: Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 11:29
por lugab
Maligno,
Era isso mesmo o que eu queria ver, pra aprender a isolar linha-por-linha:
Assunto resolvido.
Pablo César, é verdade mesmo.
Vc tem razão e eu realmente não tinha lido tudo sobre o assunto, como pensei q fiz.
Muitíssimo obrigado a vcs 2
Gabriel
Re: Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 13:11
por alxsts
Olá!
Maligno:
permita-me um ajuste no código do segundo exemplo postado por você.
O mesmo pode falhar se o primeiro byte do separador de linha cair no limite do tamanho do bloco de leitura. É muita coincidência mas, pode acontecer.
Código: Selecionar todos
#define _kBUFFER_SIZE 4096
#define _kEOL Chr(13)+Chr(10)
*
function LerArquivo(cFName)
local nHand
local cBuff := Space(_kBUFFER_SIZE)
local cRead := ""
local cLine
local i
//
// Abertura do arquivo (checagens de erro serão ignoradas)
nHandle := FOpen(cFName)
//
// Leitura do arquivo sequencialmente
while (n := FRead(nHand,@cBuff,_kBUFFER_SIZE)) > 0
cRead += Left(cBuff,n)
// procura só o Chr(13) em cRead
while (i := At( Left( _kEOL, 1 ), cRead)) > 0
// se encontrou, verifica se o byte seguinte é o Chr(10)
IF Substr( cRead, i, 2 ) == _kEOL )
// encontrou Chr(13) + Chr(10)... processa linha
cLine := Left(cRead,i-1)
cBuff := SubStr(cRead,i+Len(_kEOL))
//
// -----------------------------------------------
// Nesse ponto você tem em cLine uma linha isolada
// -----------------------------------------------
//
ENDIF
end
// lê mais um bloco do arquivo, se existir
cBuff := Space(_kBUFFER_SIZE)
end
*
if !Empty(cRead)
// Se em cRead restar algum texto significa que a última linha
// do arquivo não possui o terminador CR/LF. Pode acontecer.
end
FClose(nHand)
return nil
Interessante que, em outro tópico de uns tempos passados, você observou esse detalhe. Ou seja, aprendi com você...
Re: Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 15:40
por Maligno
Você fez uma ótima observação. Muitas pessoas acabam esquecendo desses pequenos detalhes. Eu próprio nem me lembrava mais. No Windows tenho classe que cuida desses detalhes. Acabei me acostumando mal. Mas são exatamente essas pequenas coisas que, por obra da coincidência, acabam detonando o código que achávamos a prova de bala. Obrigado pela lembrança.
No entanto, o código está correto como publiquei e funcionará sem esse problema, mesmo que tenhamos um CR como último byte da linha. Note que a variável "cRead" é uma acumuladora. Na iteração em que o par CR/LF estiver "dividido", ela estará acumulando o conteúdo ainda não processado, tendo CR como último byte. Na iteração seguinte, nova leitura será feita no arquivo e o byte LF, agora presente no início de cBuff, será então agregado ao CR pela soma da string recém-lida com o conteúdo acumulado em cRead (linha 16 do código). Nesse ponto teremos o par CR/LF detectável e o processo transcorrerá normalmente.
Re: Fread em TXT com tamanho variável de linha...
Enviado: 19 Fev 2011 23:32
por alxsts
Olá!
Maligno, você está coberto de razão.
Não sei por que razão não vi que o loop externo garante o funcionamento da rotina.
Parodiando o que você escreveu:
mas são exatamente essas pequenas coisas que, por obra da falta de atenção, acabam detonando o post que eu achava à prova de bala. Obrigado pela lembrança.
Re: Fread em TXT com tamanho variável de linha...
Enviado: 20 Fev 2011 02:31
por Maligno
C'est la vie, mon ami.

Re: Fread em TXT com tamanho variável de linha...
Enviado: 24 Fev 2011 18:32
por billy1943
Eu somente queria perguntar ao Lugab que iniciou o tópico, se o problema era somente saber o tamanho (variável) da linha do arquivo
texto, para o que os colegas apresentaram várias sugestões.
Porque do jeito que ele exemplificou ficaram outras questões em aberto, tais como:
- quantos campos esse arquivo apresenta ?
- como saber onde um campo começa e onde termina, visto que não existem separadores ?
- esse arquivo é produzido de que forma ?
- é importado de algum sistema ou programa (Word, Excel, Access) ?
Fread em TXT com tamanho variável de linha...
Enviado: 24 Fev 2011 21:59
por Pablo César
lugab escreveu:Assunto resolvido.
O Gabriel tinha dado por encerrado o tópico, entende-se que ele não precisava maiores explicações, outra porque esses assuntos que você levantou (grande parte) foram abordadas no primeiro link que indiquei. Mas se você Billy tiver alguma outra dúvida, esteja a vontade.
Re: Fread em TXT com tamanho variável de linha...
Enviado: 25 Fev 2011 12:04
por lugab
Isso mesmo Billy, o Pablo ta certo mas eu posso te ajudar, então, vamos lá...
quantos campos esse arquivo apresenta ?
A recuperação do arquivo é feito linha por linha, com linhas de tamanho variavel, delimitadas por chr(13) e chr(10).
Por se tratarem de tamanhos variáveis, certamente, os primeiros bytes da linha identificam o grupo de dados a q ela pertence, exempló: se a linha comçar com "10", os campos dela estão definidos no manual na parte de "grupo de linhas 10", se começar com "11" é outro grupo, entendeu ?
como saber onde um campo começa e onde termina, visto que não existem separadores ?
Mesam resposta de anterior
esse arquivo é produzido de que forma ?
Tanto faz. Ele Pode ser criado com set printer do "nome-do-aquivo" ou com Fwrite(), q o resultado será o mesmo
é importado de algum sistema ou programa (Word, Excel, Access) ?
Não. Ele é um arquivo texto padrão, utf8 ou não, desses utilizados pra integrar sistemas diferentes.
Gabriel