Página 1 de 1
FWrite()
Enviado: 18 Ago 2009 13:23
por Hasse
Boa tarde colegas.
Tenho um arquivo txt com os seguintes dados:
Código: Selecionar todos
315640-10/08/2009-......etc.
315641-11/08/2009-......etc.
315642-11/08/2009-......etc.
315645-14/08/2009-......etc.
315646-14/08/2009-......etc.
315647-15/08/2009-......etc.
Este arquivo crescerá muito rapidamente.
Preciso inserir o valor "315645-19/08/2009-......etc." Ele deverá ser inserido logo após 315645-18/08/2009-.....etc., e deverá ficar assim:
Código: Selecionar todos
315640-10/08/2009-......etc.
315641-11/08/2009-......etc.
315642-11/08/2009-......etc.
315645-14/08/2009-......etc.
315645-19/08/2009-......etc. <<<---- linha inserida.
315646-14/08/2009-......etc.
315647-15/08/2009-......etc.
É possível fazer isto usando o FWrite() sem alocar o arquivo numa variável de memória, localizar a posição, inserir a linha e depois gravar
Ou seja, fazer a operação diretamente no arquivo

Como
Detalhe: A data será crescente sempre. Desta forma a busca poderá ser pelo número da nova linha+1, e inserir esta nova linha antes daquela.
Re: FWrite()
Enviado: 18 Ago 2009 18:49
por Itamar M. Lins Jr.
Ola!
fseek posiciona o ponteiro.
Código: Selecionar todos
FSeek( <nFileHandle>, <nBytes>, [<nOrigin>] ) --> nPosition
But, o critério e que são elas.
Eu penso que deverás usar xString := memoread('arq.txt'), depois "at()" para achar
Código: Selecionar todos
At( <cSearch>, <cString>, [<nStart>], [<nEnd>] ) --> nPos
Saudações,
Itamar M. Lins Jr.
Re: FWrite()
Enviado: 18 Ago 2009 19:32
por Hasse
Olá Itamar.
É realmente estou perdendo a esperança de fazer uma rotina como aquela que eu estava pensando.
Eu já estou fazendo como você está sugerindo. O Problema é que a "coisa" é meio complicada, pois quando desejop inserir um número ainda inexistente a função AT() não o encontra. veja:
Código: Selecionar todos
315640-10/08/2009-......etc.
315641-11/08/2009-......etc.
315642-11/08/2009-......etc.
315646-14/08/2009-......etc.
315647-15/08/2009-......etc.
Quando quero inserir a linha "315644-16/08/2009-......etc." o AT() retorna "0" (zero) pois não encontra o endereço correto.
Código: Selecionar todos
315640-10/08/2009-......etc.
315641-11/08/2009-......etc.
315642-11/08/2009-......etc.
315644-14/08/2009-......etc. <<-- linha inserida.
315646-14/08/2009-......etc.
315647-15/08/2009-......etc.
Tive que usar um loop com o DO WHILE .T. e testar linha por linha, e assim a rotina ficou meio complicada. No início eu pensei que iria ficar lenta, mas mesmo com 5000 linhas, a rotina "voa".
Mas, ...... "se não tem solução, solucionado está"..... Vai ter que ficar do jeito como está.
Obrigado pela força.
Re: FWrite()
Enviado: 19 Ago 2009 00:48
por alxsts
Saudações a todos!
Interessante esse problema mas não acho difícil resolver.
A saida mais elegante e rápida seria usando as funções de baixo nível:
1- abrir o arquivo de entrada com FOpen()
2 - Criar( FCreate() ) um arquivo de saida ( FCreate() cria um arquivo e já o deixa aberto )
3 - ler o arquivo de entrada linha a linha com FRead() (voce sabe o comprimento de cada linha)
4 - comparar a chave dessa linha com a que voce quer incluir; se a chave da linha for menor ou igual à chave a incluir, gravar a linha do arquivo de entrada no arquivo de saida e voltar a ler (passo 3). Caso contrario, gravar a linha do arquivo de entrada no arquivo de saida, gravar a nova linha e voltar ao passo 3. Para gravar, FWrite()
5 - FClose() nos dois arquivos
Essas funções de baixo nível são muito rápidas mesmo.
Uma saida aparentemente absurda e pouco elegante, seria criar um dbf com um campo do tamanho do teu registro, fazer um Append From, incluir a nova linha, indexar (talvez com Left( campo, n ) ) e exportar como SDF para um novo arquivo texto. Essa saida dá pra fazer na mão por um DBU da vida e é até válida para um arquivo muito grande, desde que não seja necessário fazer isso todo dia...
Penso que voce deve avaliar, conforme o número de vezes que precisará repetir esse processo, a possibilidade de manter esses dados em um DBF, indexado pelo código + DTOS( data ). Assim, as inclusões seriam mais fáceis. Se o arquivo é por data e cresce muito, gere arquivos diários, separados. Em qualquer das opções, se precisar das informações em formato TXT, será fácil exportar.
Re: FWrite()
Enviado: 19 Ago 2009 08:54
por Hasse
Bom dia alxsts.
Eu já estou lendo e gravando com estas funções de baixo nível, justamente por serem muita rápidas.
A tua idéia de comparar linha a linha durante a leitura é muito boa, e acho que vale a pena implantar. Hoje estou fazendo a comparação na variável de memória, em um loop WHILE.
O comprimento das linhas não é padrão, mas isto não é problema já que posso detectar a presença do CHR(13+CHR10) que está no final de cada linha para separar elas, como já faço hoje.
Eu não gostaria de arquivar os dados em DBF, mas se este sistema em txt não der certo, fatalmente terei que optar por trocar o txt pelo dbf.
A consulta será praticamente diária, ou pelo menos 3x por semana, a exportação e impressão ainda não sei. O uso é que vai determinar.
Valeu. A tua idéia é foi muito boa.
Re: FWrite()
Enviado: 19 Ago 2009 12:14
por alxsts
Saudações Hasse e demais amigos,
Na verdade, isso é um merge... Mas cometi um erro de lógica:
4 - comparar a chave dessa linha com a que voce quer incluir; se a chave da linha for menor ou igual à chave a incluir, gravar a linha do arquivo de entrada no arquivo de saida e voltar a ler (passo 3). Caso contrario, gravar a linha do arquivo de entrada no arquivo de saida, gravar a nova linha e voltar ao passo 3. Para gravar, FWrite()
O correto é:
4 - comparar a chave dessa linha com a que voce quer incluir; se a chave da linha for menor ou igual à chave a incluir, gravar a linha do arquivo de entrada no arquivo de saida e voltar a ler (passo 3).
Caso contrario, gravar a nova linha que voce quer incluir (para ficar na ordem) e gravar a linha do arquivo de entrada no arquivo de saida. Voltar ao passo 3 e executar até o fim do arquivo de entrada. Para gravar, FWrite()
FWrite()
Enviado: 14 Fev 2022 11:38
por clodoaldomonteiro
Aqui tem um exemplo do xHarbour usando a função HB_FUse().
Código: Selecionar todos
// The example implements a simple text file viewer using a
// TBrowse object and text file functions.
#include "Common.ch"
#include "Inkey.ch"
#include "TBrowse.ch"
PROCEDURE Main( cFile )
LOCAL nFile, oTBrowse
SET CURSOR OFF
nFile := HB_FUse( cFile )
IF nFile < 1
? "File not found", cFile
QUIT
ENDIF
oTBrowse := TxtBrowse()
RunTxtBrowse( oTBrowse )
HB_FUse()
RETURN
PROCEDURE RunTxtBrowse( oTBrowse )
LOCAL nKey, nLen, lRun := .T.
DO WHILE lRun
oTBrowse:forceStable()
nKey := Inkey(0)
SWITCH nKey
CASE K_LEFT
IF oTBrowse:cargo > 1
oTBrowse:cargo --
oTBrowse:refreshAll()
ENDIF
EXIT
CASE K_RIGHT
oTBrowse:cargo ++
oTBrowse:refreshAll()
EXIT
CASE K_HOME
IF oTBrowse:cargo > 1
oTBrowse:cargo := 1
oTBrowse:refreshAll()
ENDIF
EXIT
CASE K_END
nLen := Len( HB_FReadLN() )
IF nLen-oTBrowse:cargo+1 > 72
oTBrowse:cargo := nLen - 72 + 1
oTBrowse:refreshAll()
ENDIF
EXIT
CASE K_CTRL_HOME
EXIT
CASE K_CTRL_END
EXIT
DEFAULT
IF oTBrowse:applyKey( nKey ) == TBR_EXIT
lRun := .F.
ENDIF
END
ENDDO
RETURN
FUNCTION TxTBrowse( nT, nL, nB, nR )
LOCAL oTBrowse, oTBCol1, oTBCol2
DEFAULT nT TO 0, ;
nL TO 0, ;
nB TO MaxRow(), ;
nR TO MaxCol()
oTBrowse := TBrowseNew( nT, nL, nB, nR )
oTBrowse:cargo := 1
oTBCol1 := TBColumnNew( " ", ;
{|| Padr(HB_FRecno(),5)+":" } )
oTBCol2 := TBColumnNew( " ", ;
{|| Padr( SubStr( HB_FReadLN(), oTBrowse:cargo), 72 ) } )
WITH OBJECT oTBrowse
:addColumn( oTbCol1 )
:addColumn( oTbCol2 )
:goTopBlock := {|| HB_FGotop() }
:goBottomBlock := {|| HB_FGoBottom() }
:skipBlock := {|n| TxtSkipper(n) }
:colPos := 2
END
RETURN oTBrowse
FUNCTION TxtSkipper( nRequest )
LOCAL nSkip := 0
DO CASE
CASE nRequest == 0
CASE nRequest < 0
DO WHILE nSkip > nRequest .AND. HB_FRecno() > 1
HB_FSkip(-1)
nSkip --
ENDDO
CASE nRequest > 0
DO WHILE nSkip < nRequest
HB_FSkip(1)
IF HB_FEof()
EXIT
ENDIF
nSkip ++
ENDDO
ENDCASE
RETURN nSkip
FWrite()
Enviado: 15 Fev 2022 00:44
por alxsts
Olá!
A navegação não funciona...
FWrite()
Enviado: 15 Fev 2022 08:06
por paiva
grava em um dbf e depois faz um copy caso precise em txt rs