Manipulação de Texto
Originalmente publicado na Universal Thread Magazine
http://www.UTMag.com/Portuguese
Neste artigo, eu irei mostrar várias maneiras de manipular arquivos texto. O conhecimento deste métodos é muitas vezes importante para importar e exportar em formatos específicos.
Algumas destas técnicas podem também ser usadas para trabalhar com arquivos de qualquer conteúdo; entretanto, neste artigo iremos nos concentrar nos arquivos textos.
Quando você precisa manipular arquivo texto?
Deve haver muitos casos onde você precise criar ou ler arquivos texto (ou arquivos binários, em alguns casos), por exemplo:
-
Você precisa importar dados de outro programa para dentro de sua aplicação.
-
Você precisa exportar dados da sua aplicação, para um formato muito específico, solicitado por outra aplicação.
-
Você quer gerar uma saída HTML automaticamente, por exemplo, como uma nova opção de relatório, para enviar via e-mail atachado, ou para publicar em um Site na Web.
-
Você quer imprimir para uma impressora matricial. Isto faz a impressão em modo texto conveniente, isto em algumas impressoras pode tornar a impressão 2 ou 3 vezes mais rápida, ou mais ainda, se você usar o relatório padrão.
Note que para interfacear com outros programas, importar e exportar para arquivos texto ou arquivos binarios não é a única opção. Outras opções, por exemplo, arquivos XML (que são atualmente arquivos texto especiais), ODBC e Automação, estão alem do escopo deste artigo.
Deve haver muitos casos onde você precise criar ou ler arquivos texto (ou arquivos binários, em alguns casos), por exemplo:
-
Você precisa importar dados de outro programa para dentro de sua aplicação.
-
Você precisa exportar dados da sua aplicação, para um formato muito específico, solicitado por outra aplicação.
-
Você quer gerar uma saída HTML automaticamente, por exemplo, como uma nova opção de relatório, para enviar via e-mail atachado, ou para publicar em um Site na Web.
-
Você quer imprimir para uma impressora matricial. Isto faz a impressão em modo texto conveniente, isto em algumas impressoras pode tornar a impressão 2 ou 3 vezes mais rápida, ou mais ainda, se você usar o relatório padrão.
Note que para interfacear com outros programas, importar e exportar para arquivos texto ou arquivos binarios não é a única opção. Outras opções, por exemplo, arquivos XML (que são atualmente arquivos texto especiais), ODBC e Automação, estão alem do escopo deste artigo.
Comando padrão para importar e exportar
Os comandos padrão par importar e exportar arquivos texto são APPEND FROM (para importa) e COPY TO (para exporta). Eles são relativamente fáceis de usar, porque eles não requerem que você faça um loop através do registros. - Estes comandos pode processar uma tabela inteira de uma só vez. O fato de você usar uma simples comando também torna estes comandos muito rápidos.
Dois formatos texto comuns são suportados. Com uma virgula delimitando o arquivo texto, cada campo é separado do próximo por uma virgula, (outros caracteres também são suportados). Com um tamanho-fixo de arquivo texto, cada campo é identificado somente por sua posição. Por exemplo, os primeiros 10 bytes em cada registro deve corresponder ao primeiro campo, os próximos 3 bytes ao segundo campo, etc. Em ambos os casos, os registros são separados por simbolo padrão de nova-linha. (carriage-return e line-feed, que correspondes a chr(13) + chr(10)). Os comandos correspondentes são DELIMITED e SDF.
Para exportar para um arquivo texto, apenas seleciona uma tabela ou prepare um cursor, e use o comando similar a:
copy to MyText.txt type SDF
* (or: type delimited)
|
Para importar um arquivo texto para uma tabela, você precisa preparar a tabela ou cursor com a correta estrutura primeiro.
Estes comandos são muito apropriados para uma rápida importação ou exportação, mais se seu arquivo texto tiver (ou necessitar de) um formato muito específico, você precisará de alguns comandos adicionais, para os quais eu dediquei o restante de artigo.
FileToStr(), StrToFile(), alines() e mline()
Um relatório padrão do VFP pode ter como saída um arquivo texto:
report form TestReport to file output.txt ascii
|
FileToStr(), StrToFile(), alines() e mline()
No VFP 6 ou superior, você pode usar FileToStr() e StrToFile() para copiar rapidamente de um arquivo no disco para uma variável de memória, ou para outro meio de saída.
O exemplo a seguir cria um arquivo texto com dez linhas:
erase output.txt
for i = 1 to 10
StrToFile("Line " + trans(i) + chr(13) + chr(10), "output.txt", .T.)
next
|
Note que se o terceiro parametro é .T., a saída será acrescentada ao arquivo, ao invés de sobrescreve todo o arquivo.
Para importar dados, a função alines() é especialmente facil de usar, Ela irá conveter cada linha para dentro de uma matriz.
Para o exemplo a seguir mostrarei como converter o arquivo autoexec.bat, adicionando numero de linha à esquerda:
for i = 1 to alines(laMyText, FileToStr("c:\autoexec.bat"))
? transform(i, "###"), laMyText(i)
next
|
A Manipulação com alines() é muito rápida, também. Todavia, infelizmente, o VFP tem uma limitação de 65.000 elementos por vetor traduzindo para um máximo de 65.000 linhas de texto por aquivo.
Se você necessitar usar mais linhas, ou tem planos para crescimento futuro, você pode usar a função mline(). O arquivo help declara que ela se destina para uma campo memo, mais ela trabalha muito bem com longas expressões de caracter na memória, também.
E ireia agora repetir o exemplo anterior, usando a função mline(). Desde a idéia seja para usar este tipo de código na possibilidade de uma arquivo grande, o exemplo é otimizado para ter velocidade em duas partes: 1) Eu uso a variavel _mline, como explicado no help do VFP. 2) Eu não necessitei contar o numero total de linha antecipadamente, com memlines(). O primeito ponto é especialmente importante. Por exemplo, se você usa mline() para retornar a linha #1000 diretamente, o VFP deve primeiro pesquisar pelo fim da linha de caracteres até as primeira 999 linhas para seu pedido de encontrar a linha de número 1000.
set memowidth to 200
lcMyText = FileToStr("c:\autoexec.bat")
_mline = 0
i = 0
FileSize = len(lcMyText)
do while _mline < FileSize – 1
i = i + 1
? transform(i, "###"), mline(lcMyText, 1, _mline)
enddo
|
Isto irá resolver a limitação alines para o máximo de 65.000 elementos no vetor. Entretanto, lendo um grande arquivo dentro da RAM em um simples peça pode ser muito lento, se o arquivo é maior que memória RAM livre (Isto normalmente acontece, mais o uso de memória virtual pode tornar as coisas consideravelmente lentas) Se este é o caso, eu recomento o uso de funções de arquivo de baixo-nivel ao invés da outra opção.
Low-level file-functions
Funções de arquivo de Baixo-Nivel (LLFF) dão a você um último controle sobre cada e todos os bytes que você importa ou exporta, Primeiro, como um exemplo, vamos repetir o exemplo que mostra o arquivo autoexec.bat, desta vez com LLFF:
lnFile = fopen("c:\autoexec.bat")
if lnFile < 0
MessageBox("Error opening file.")
else
i = 0
do while not feof(lnFile)
i = i + 1
? transform(i, "###"), fgets(lnFile)
enddo
fclose(lnFile)
endif
|
Os LLFF são um pouco mais complicados que os métodos explicados anteriormente, Eu tentarei explicar cada passo.
Primeiro, um arquivo existente é aberto com fopen(), (ou para caso de exportar) um novo arquivo é criado com fcreate().
Estas funções retornam um "arquivo handle", um número que deve ser armazenado em uma variável, no pedido de acesso ao mesmo arquivo mais tarde no programa. Se o arquivo puder ser aberto ou criado com sucesso, um numero positivo é retornado. Um -1 indica algum problema. (Note que eu não inclui a manipulação de erro nos outros exemplos - Eu estou assumindo que o arquivo exite.)
Um linha toda pode ser lida de um arquivo aberto desta forma, com a funçao fgets(). Para saída, uma linha inteira pode ser escrita com fputs(). Se você precisa trabalhar com bytes indivíduais, você pode usar fread() e fwrite().
Para importar dados, você irá usualmente querer continuar lendo dados até você descobrir o fim do arquivo, o qual você detecta com feof(). Depois de você fazer todo o processo necessário, antes de você abrir um arquivo existente ou criar um novo arquivo ele terá que ser explicitamente fechado, com fclose()
Para mater o padrão, aqui esta um exemplo para o caso de exportar. Neste programa criarei um pequeno arquivo texto usando LLFF:
lnFile = fcreate("output.txt")
if lnFile < 0
MessageBox("Error creating file.")
else
fputs(lnFile, "Line 1")
fputs(lnFile, "Line 2")
fclose(lnFile)
endif
|
Saida com ? e ??
Os comandos ? e ?? (trataremos destes comandos nas duas próximas secções) são somente para o caso de exportar, que iremos criar o arquivo texto.
Ambos os comandos ? e ?? mostrarão a expressão especificada. Se você especificar mais que uma expressão, separadas com vírgula, Eles estarão automaticamente separados por um espaço. Entretanto, separar o comando ? não adiciona este espaço.
?? adicionará uma nova linha para a saída, ? não fará isto. Note que ao contrário dos comandos similares em outras línguagens, a linha é adicionada antes do resto da saída especificada no comando. Por padrão, a saída irá para o vídeo.
Agora, vamos ver um pequeno exemplo, de como produzir um arquivo texto com estes comandos, Com o propósito de ilustração, eu separei o código para produzir a segunda linha dentro de dois comandos separados.
* Setup code
set console off
set alternate to output.txt
set alternate on
* Produz a Saída
?? "This is line 1"
? "This", "is"
?? " line", "2"
* Limpa o código
set alternate off
set alternate to
set console on
|
Uma vez que você já configurou SET ALTERNATE para um arquivo, a saída de diversos outros comandos, como LIST, LIST STRUCTURE e DIR, irão também sair no seu arquivo texto.
Saída com @...SAY
O comando @...SAY, que também envia o resultado por padrão para o video, é uma outra opção para criar arquivo texto.
Este comando deixam você especificar as coordenadas da saída de seu arquivo texto imediatamente. Em outras palavras, você pode especificar uma linha ou número de coluna diretamente, sem explicitamente linhas ou colunas vázias. Entretanto, a saída deverá ser produzida em ordem ascendente. O VFP trata a saída como se fosse uma impressora, o que signífica que ir para tráz para uma linha anterior irá inserir um salto de página.
set device to file output.txt
@ 0, 10 say "This is the title"
@ 3, 0 say "Some text"
@ 2, 0 say "This would go to the next page"
set device to screen
|
O Visual FoxPro mantém a par das posições das linhas e colunas; isto pode ser acessado com as funções row() e col(), ou podem apenas ser impressas relativamente para a posição corrente com um operador especial $ indicando o numero da coordenada:
set device to file output.txt
@ 1, 0 say "Hello"
@ $, $+2 say "World"
@ $+3, 0 say "Some more text"
set device to screen
|
Infelizmente, o tópico do help para estes versáteis comandos diz apenas que estão "incluidos para compatibilidade anteriores". Para mais detalhes, você terá que consequentemente ve-las no arquivo help do Foxpro 2.x.
Saída com TEXTMERGE
Outra alternativa para criar arquivo texto é o uso dos comandos TEXT e SET TEXTMERGE. Você pode uma ou outra linhas de saída do texto com \ e \\, ou para evitar o uso repetido destes símbolos em diversas linhas consecutivas, entre TEXT e ENDTEXT. O exemplo seguinte ilustra como fazer isto:
set textmerge on to output.txt noshow
\\Line 1
\Line 2
text
Line 3
Line 5
Hoje é <>, <>.
Seu hard disk tem <> bytes livres.
endtext
set textmerge to
|
Note que quando você combina o texto constante com as variáveis ou as expressões, seu código é muito mais legível com estes comandos, do que com as outras alternativas mostradas.
Manipulando arquivos binários
Todos os exemplos anteriores são para arquivos texto. Você pode usar algumas das opções para arquivos binários, que são, arquivos em qualquer formato. Por exemplo, ? e ?? pode mostrar qualquer expressão, não apenas texto plano; StrToFile() e FileToStr() podem trabalhar como ambos text e dados binários, e as funções de baixo nível pode trabalhar com linhas inteiras de texto, e um byte individual.
O problema real com arquivos binários, claro, é que um formato binário deve ser um pouco complicado, e ele deve ser difícil de se obter a documentação em detalhes de como o arquivo esta armazenado.
Imprimindo
Se você quer imprimir seu arquivo texto no modo texto, você pode usar o comando "???" para enviar código para a impressora, seguido por seu arquivo texto, diretamente para a impressora. Nenhuma interpretação é feita pelo sistema impressão do Windows - mesmo que a quebra-de-página tem que ser adicionado explicitamente (verifique em seu manual da impressora - para impressoras padrão da ponto-matricial Epson, ele é chr(12)).
Também, faça download na Universal Thread como #9957, de Ed Rauh, é uma classe projetada especificamente para contornar o sistema impressão do Windows, e imprime diretamente à impressora.
Eu criei uma classe para cuidar de muitos detalhes repetivos da criação de relatórios em modo texto (como a programação do laço principal e tomar cuidado de expressões da ruptura, entre outras). Ela esta disponível para download na Universal Thread como #9991. Outros relatórios texto estão disponíveis também, mais eu não os testei completamente.
Conclusão
O Visual Foxpro oferece a você várias alternativas para acessar arquivos texto. E é muito provável que mais cedo ou mais tarde, você precisará de algum deles, para as finalidades esboçadas no começo deste artigo.
Pablo van Diest (Buenos Aires, Argentina) é Desenvolvedor Sênior em Merino Aller, uma empresa produtora de software ERP para América Latina e Espanha. Pode ser contatado em
p
ablov@merino.com.a
r
.
Faça o download deste documento:
Manipulação de Texto
formato Word, 512 KB