FWrite()

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Hasse
Usuário Nível 4
Usuário Nível 4
Mensagens: 820
Registrado em: 19 Out 2004 10:30
Localização: Jaraguá do Sul - SC

FWrite()

Mensagem 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.
Hasse
CP200 / CP500 / Basic / dBase III / dBase IV / Clipper Summer / RTlink / Exospace.
Clipper 5.3b / Blinker 7.0 / CDX com TAG
xHarbour 1.2.1-6604 / Borland C++ (5.5.1) 32 bit / HBmake.
Harbour 3.2.0dev (r1412121623) / MINGW / HBM2 / MiniGui HMG 3.1.4 / IDE (Roberto Lopez).
"Conheça todas as teorias, domine todas as técnicas, mas, quando tocares uma alma humana, seja apenas outra alma humana." (C.G.Jung)
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Re: FWrite()

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Hasse
Usuário Nível 4
Usuário Nível 4
Mensagens: 820
Registrado em: 19 Out 2004 10:30
Localização: Jaraguá do Sul - SC

Re: FWrite()

Mensagem 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.
Hasse
CP200 / CP500 / Basic / dBase III / dBase IV / Clipper Summer / RTlink / Exospace.
Clipper 5.3b / Blinker 7.0 / CDX com TAG
xHarbour 1.2.1-6604 / Borland C++ (5.5.1) 32 bit / HBmake.
Harbour 3.2.0dev (r1412121623) / MINGW / HBM2 / MiniGui HMG 3.1.4 / IDE (Roberto Lopez).
"Conheça todas as teorias, domine todas as técnicas, mas, quando tocares uma alma humana, seja apenas outra alma humana." (C.G.Jung)
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Re: FWrite()

Mensagem 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.
[]´s
Alexandre Santos (AlxSts)
Hasse
Usuário Nível 4
Usuário Nível 4
Mensagens: 820
Registrado em: 19 Out 2004 10:30
Localização: Jaraguá do Sul - SC

Re: FWrite()

Mensagem 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.
Hasse
CP200 / CP500 / Basic / dBase III / dBase IV / Clipper Summer / RTlink / Exospace.
Clipper 5.3b / Blinker 7.0 / CDX com TAG
xHarbour 1.2.1-6604 / Borland C++ (5.5.1) 32 bit / HBmake.
Harbour 3.2.0dev (r1412121623) / MINGW / HBM2 / MiniGui HMG 3.1.4 / IDE (Roberto Lopez).
"Conheça todas as teorias, domine todas as técnicas, mas, quando tocares uma alma humana, seja apenas outra alma humana." (C.G.Jung)
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Re: FWrite()

Mensagem 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()
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
clodoaldomonteiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 821
Registrado em: 30 Dez 2006 13:17
Localização: Teresina-PI
Contato:

FWrite()

Mensagem 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
At. Clodoaldo Monteiro
Linguagens: Clipper / Harbour
Área de Atuação: Sistemas de gestão para Prefeituras Municipais
Fones: (86)3223-0653, 98859-0236
www.simplesinformatica.com.br
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

FWrite()

Mensagem por alxsts »

Olá!

A navegação não funciona...
[]´s
Alexandre Santos (AlxSts)
paiva
Usuário Nível 3
Usuário Nível 3
Mensagens: 300
Registrado em: 04 Ago 2005 10:28

FWrite()

Mensagem por paiva »

grava em um dbf e depois faz um copy caso precise em txt rs
Responder