Como não estava funcionando, apaguei o código,
mas vou refazer e assim que estiver lhe mando
Já que vai refazer, vou lhe dar uma dica que vai tornar sua tarefa bem mais fácil. Tudo o que fazemos em programação é PROBLEMA e não dá pra fugir disso. Mas o "pulo-do-gato" pra conseguir se dar bem nessa área é saber resolver os problemas de forma eficaz e, principalmente, simples. O truque é resolver o problema dividindo-o em problemas menores, e resolvê-los um a um. Daí vem o termo abstração. A forma "canônica" de fazer isso é chamada de programação "top-down", ou seja, de cima pra baixo. Quando chegar ao nível mais inferior, acabou o problema principal, que gerou os menores. Essa discussão é filosófica e não cabe numa simples thread. Infelizmente os "cursos" que se encontram na Internet tratam apenas dos aspectos mais imediatistas e ignoram as metodologias. É sempre assim: as matérias "chatas" são postas de lado para que se possa privilegiar o lado mais "palpável" e, claro, mais excitante da programação. Aí é que os problemas do programador realmente começam.
Mas vou tentar lhe dar um exemplo simples, com base no problema que você quer resolver. A sua necessidade é pesquisar por uma string qualquer num arquivo texto. Como já disseram, você pode importar tudo para um DBF e pesquisar os campos. Eu já disse e repito que é muito melhor fazer pela leitura direta do arquivo texto. Só não é mais fácil porquê isso envolve muito mais manipulação de string que o normal. Mas isso é coisa que você precisa saber. Quem trabalha com sistemas de informação precisa ser "cobra" em manipulação de strings. Do contrário, vai viver sofrendo com coisas pequenas. Então, não adianta ficar fugindo disso. Se não for um "malabarista" de strings, prepare-se e faça tudo para sê-lo.
Voltando ao problema principal: nada se faz bem feito sem metodologias apropriadas para o contexto que será abordado. No caso, como eu já disse, você precisa dividir o problema, criando uma abstração ou, como alguns costumam dizer, elevando o nível do problema, dividindo-o em problemas menores, de níveis mais baixos. Imagine (ou fantasie) uma solução ideal. Veja como fica simples:
Código: Selecionar todos
function PesqString(cArq,; // nome do arquivo alvo da pesquisa
cStr ; // string que se precisa procurar
)
if !AbreArq()
// Não deu pra abrir: fim
return
end
*
while .T.
cLine := ReadText()
if cLine = nil
// Foi sinalizado que não há mais linhas
exit
end
//
// Neste ponto você tem o conteúdo de uma linha
// Com o conhecimento que tem de manipulação de
// strings, procure a string nesta linha e faça
// o que tiver de ser feito. Se encontrou e não
// precisar continuar, simplesmente retorne com
// o resultado ou continue lendo até o fim. Vai
// da sua necessidade.
//
cResult :=
end
Mais fácil que isso, impossível. Você abre o arquivo e lê linha por linha até o fim. A cada leitura, verifica se existe a string procurada. A cada iteração, cLine será checada. Se o conteúdo dela for NIL, estará sinalizado o fim do arquivo. Nada mais há para ser lido. Encerra-se o trabalho, devolvendo à rotina chamadora o resultado encontrado. A variável cResult é apenas ilustrativa.
Nessa etapa você já abstraiu o máximo que pôde e resolveu seu problema principal de maneira simples e muito eficiente. Aliás, note como a legibilidade melhora bastante. Nada daqueles emaranhados de códigos para atrapalhar. Fica perfeito desta forma.
Mas lembre-se de que a nossa intenção era dividir o problema principal. Isso já fizemos. Agora, na próxima etapa, temos de resolver os outros problemas menores, criados para resolver o problema principal.
De imediato pensamos na função AbreArq(). No Clipper já existe função para a abertura de arquivos. Será apenas o caso de substituirmos essa chamada pela função do próprio Clipper. Como na função já existe um parâmetro para o nome do arquivo, podemos usar:
Código: Selecionar todos
function PesqString(cArq,; // nome do arquivo alvo da pesquisa
cStr ; // string que se precisa procurar
)
local nHandle
if (nHandle := FOpen(cArq)) = -1
return // retorne um indicador qualquer de erro
end
...
Agora a parte mais trabalhosa: precisamos ter a função ReadText() que faça o "trabalho sujo" e chato da leitura de linha por linha, sem se perder. É chato, é trabalhoso, mas se você tiver uma função dessas funcionando perfeitamente, você não só vai resolver esse seu problema, como muitos outros problemas semelhantes. Isso é que é legal na programação. Você constrói blocos de códigos e utiliza-os sempre que precisar, sem precisar alterar uma vírgula neles. Fiz uma adaptação da função que deixei na outra thread:
Código: Selecionar todos
#define _kSIZE 2048
#define _kEOL Chr(13)+Chr(10)
static cBuff // o buffer de armazenamento
static lCont // se TRUE, o sistema só precisará continuar analisando
// o buffer, que provavelmente, ainda deve conter dados
//------------------------------------------------------------------
function ReadText(nHandle) // se nHandle=0, reinicialize o sistema
local nByts // bytes lidos na iteração
local cBuff := Space(_kSIZE) // buffer de armazenamento
local cRest := "" // resto da leitura
local cLine // a linha recuperada do arquivo
local i // indexador
*
if nHandle = 0
cBuff := Space(_kSIZE) // zerar o buffer
lCont := .F. // indicar um início de leitura do arquivo
FSeek(nHandle,0) // ajustar o ponteiro do arquivo no início
return nil // ok, sistema reinicializado
end
*
while lCont .or.;
(nByts := FRead(nHandle,@cBuff,_kSIZE)) > 0 .or.;
!Empty(cRest)
if !lCont
cBuff := RTrim(cBuff)
cBuff := cRest+cBuff
cBuff += if(nByts=0 .and. Right(cBuff,2) != _kEOL, _kEOL, "")
end
*
if (i := At(_kEOL,cBuff)) > 0
cLine := Left(cBuff,i-1) // a linha, sem o par CR/LF
cBuff := SubStr(cBuff,i+2) // descartado CR/LF do buffer
lcont := .T. // sinalizar a continuação
//
// Retornar a linha atualmente focalizada
return cLine
end
cRest := cBuff
cBuff := Space(_kSIZE)
lCont := .F. // neste ponto não há continuidade da leitura do
// buffer anteriormente carregado; é preciso ler
// do arquivo, como se estivessemos começando.
end
//
// Se chegou a esse ponto, não há mais o que ser lido no arquivo
return nil
NOTA: Esta função deve residir em arquivo próprio, já que ela é uma ferramenta de abstração e contém variáveis estáticas. É um componente reutilizável.
Com relação a leitura do arquivo, temos agora a solução completa. Só ficará faltando você inserir o seu código de pesquisa dentro da linha. Já preparado, eis o código final, em alto nível:
Código: Selecionar todos
function PesqString(cStr,; // string a ser procurada
cArq ; // nome do arquivo alvo da pesquisa
)
local nHandle
if (nHandle := FOpen(cArq)) = -1
return // retorne um indicador qualquer de erro
end
*
ReadText(0) // inicializa nosso sistema de leitura
while .T.
cLine := ReadText(nHandle)
if cLine = nil
* Fim de leitura: faça o que achar melhor
end
//
// Código da pesquisa dentro da linha
cResult := ...
end
Abordei o assunto de maneira bem simples. Mas se ainda tiver alguma dúvida, é só enviar outra mensagem (não em private, por favor) na thread.
E só mais um detalhe: não testei a função ReadText(). Tenho meu próprio sub-sistema de manipulação de arquivos texto, que é bem mais flexível que isso. Essa função eu tinha feito para aquela outra thread e só adaptei para você. Se der pau, tente consertar. Se tiver problema com isso, volte à esta thread novamente, para podermos ajudá-lo.
[]'s
Maligno
http://www.buzinello.com/prg