Página 1 de 1

Ler e regravar um arquivo TXT com as funções de baixo nível

Enviado: 14 Out 2013 16:41
por billy1943
Procurei de todas as formas de uso das funções FOPEN, FSEEK, FREAD, FWRITE e FCLOSE, , no NG do Clipper, para fazer o seguinte:

1. Tenho um arquivo texto (relatório gerado em .TXT) e preciso agora usá-lo no NODOSIMP que não admite caracteres de controle;

2. Pretendo gerar outro arquivo ou ainda regravar o mesmo arquivo original excluindo caracteres de controle que estão no final do arquivo (em hexadecimal OC, 0D, 20, 12, 1B, 40, 1B) e incluindo também em hexadecimal ( OD, 0A )

3. Vamos supor que o arquivo fonte tem 5.174 caracteres e pretendo excluir os últimos 7 caracteres do final do arquivo, já usei a FSEEK para obter o tamanho total, mas estou parado agora sobre como usar a FWRITE para gravar os 5.167 bytes anteriores. Depois disso, gravarei os caracteres em substituição.

Uma vez vi neste fórum uma solução apontada para retirar caracteres de controle invisíveis que estavam sobrando no final do arquivo, mas não encontrei mais esse tópico.
Esses caracteres invisíveis são gravados automaticamente por alguns editores de texto do DOS.

Ler e regravar um arquivo TXT com as funções de baixo nível

Enviado: 14 Out 2013 18:13
por Pablo César
Olá Billy,

Você precisa isso pra Clipper o Harbour ?
Uma ideia que talvez não venha ao caso mas ajude. Por quê ao invés de remover comando de impressão, você não cria sem ? Isto é, você poderia criar praticamente de forma simultânea dois arquivos: um de visualização (digamos) e o outro de impressão, talvez com extensão diferente.

Um solução bem simples eu utilizei o CharRem da Ca-Tools. Uma vez criado o arquivo, leia na memória, dependendo o tamanho (se for pra Clipper) com MemoRead e utilizas essa função para remover os caracteres de comandos e depois re-gravá-los.

Existem muitos tópicos de funções de baixo nível. Estas funções são mutos rápidas e eficientes. Só não entendi qual é a sua dúvida.

Ler e regravar um arquivo TXT com as funções de baixo nível

Enviado: 14 Out 2013 19:49
por alxsts
Olá!

Como o tópico está na seção Clipper, suponho que esta seja a linguagem usada. Como disse o colega, o ideal seria gerar o arquivo sem esses caracteres mas, na impossibilidade de fazer isto, segue o código abaixo, que faz o que você precisa (retira os últimos 7 bytes do arquivo).

É preciso verificar se esse arquivo fonte é mesmo um texto em ASCII e para que servem os caracteres que você mencionou:
billy1943 escreveu: caracteres de controle que estão no final do arquivo (em hexadecimal OC, 0D, 20, 12, 1B, 40, 1B)
É preciso verificar também se os registros são de tamanho fixo ou variável, como as linhas estão separadas (qual é o separador) se é que estão separadas, etc...

Código: Selecionar todos

#include "fileio.ch"

FUNCTION Main()

   SetMode( 25,80)
   CLS

   IF FConvert( "Teste.Txt", "Teste.New" )
      Alert( "Arquivo convertido!", , "W+/B" )
   ELSE
      Alert( "Falha ao converter o arquivo!" )
   ENDIF

RETURN NIL
//------------------------------------------------------------------------------

STATIC FUNCTION FConvert( cInFile, cOutFile )

   LOCAL lRet := .F.
   LOCAL nInFileHandle := 0
   LOCAL nOutFileHandle := 0
   LOCAL nTotalBytes
   LOCAL nBytesToWrite
   LOCAL nBytesRead
   LOCAL cBuffer

   BEGIN SEQUENCE

      IF Empty( cInFile )  .OR. ;
         Empty( cOutFile ) .OR. ;
         ( !File( cInFile ) )
         BREAK
      ENDIF

      // abre o arquivo a ser convertido
      IF ( nInFileHandle := FOPEN( cInFile, FO_READ + FO_EXCLUSIVE ) ) == -1
         BREAK
      ENDIF

      // Posiciona o ponteiro no final do arquivo e obtem o tamanho do mesmo, em bytes
      nTotalBytes := FSEEK(nInFileHandle, 0, FS_END)
      //
      // Move o ponteiro de volta para o início do arquivo
      FSEEK(nInFileHandle, 0)

      // Considerando que os 7 últimos butes serão ignorados, define o tamanho do
      // arquivo de saida em bytes
      nBytesToWrite := (nTotalBytes - 7 )

      // cria o arquivo de saída
      IF ( nOutFileHandle := FCREATE(cOutFile, FC_NORMAL))  == -1
         BREAK
      ENDIF

      // inicializa o buffer de leitura com a quantidade de espaços que se pretende ler
      cBuffer := SPACE( nBytesToWrite )

      // executa a leitura preenchendo o buffer (note que a variável cBuffer é
      // passada por referência (prefixado por @)
      nBytesRead := FREAD( nInFileHandle, @cBuffer, nBytesToWrite )

      // grava o arquivo de saída
      IF FWRITE(nOutFileHandle, cBuffer, nBytesToWrite ) == nBytesToWrite
         cBuffer := Chr(13) + Chr(10)
         // grava o separador da última linha (CR + LF ou 0D + 0A em Hexadecimal)
         IF FWRITE(nOutFileHandle, cBuffer, 2 ) == 2
            lRet := .T.
         ENDIF
      ENDIF

   END SEQUENCE

   // fechamento dos arquivos
   IF nInFileHandle  != 0  ;   FCLOSE( nInFileHandle )    ;   ENDIF
   IF nOutFileHandle != 0  ;   FCLOSE( nOutFileHandle )   ;   ENDIF

   RETURN lRet
//------------------------------------------------------------------------------
Este código demonstra a utilização das funções de baixo nível. Espero que ajude.

Ler e regravar um arquivo TXT com as funções de baixo nível

Enviado: 14 Out 2013 22:04
por billy1943
Ficou perfeito !

Apesar de não informar que preciso da rotina para sistema em Clipper, o nosso amigo Alexandre esgotou o assunto das funções de baixo nível do Clipper e está rodando exatamente como o desejado.

Eu me assustei quando vi que somente havia sido reduzido o tamanho do arquivo de saída em 5 (cinco) btyes, mas depois verifiquei que já tinham sido incluídos os caracteres hexa 0D OA ou seja o CR + LF separador da última linha gravada.

O Pablo César aventou uma possibilidade que eu já estava "maquinando" pois hoje dependendo da saída a ser dada ao relatório eu
preparo o arquivo de formas diferentes, pois posso:

1. Exibir na tela usando a função FILEREAD
2. Gravar em arquivo SPOOL com vistas à impressão futura
3. Gravar para uso pelo NODOSIMP - USB
4. Gravar para uso do WORD - USB
5. Impressão para impressora escrava de impacto (LPT1)

Mas somente gero para um único modelo e se escolher outra forma de saída tenho que produzir novamente a posição já com vistas à
saída pretendida.

Quanto aos caracteres que estão no final do arquivo informo que são controles para o tamanho dos caracteres, desabilitando
gráficos, etc., aqueles caracteres de controle do tempo das impressoras de impacto, pois tem clientes que ainda as usam...
Quando a impressão é derivada para impressoras em USB, pelo NODOSIMP ou WORD, eles podem ser dispensados.

Ler e regravar um arquivo TXT com as funções de baixo nível

Enviado: 15 Out 2013 00:17
por alxsts
Olá!

só uma observação: em Clipper, se os teus arquivos de entrada tiverem mais que 65535 bytes (64Kb) você precisará ler o arquivo em partes de até 64Kb e ir gravando essas partes no arquivo de saída (DO ... WHILE), eliminando os bytes finais da última parte.