Lidando com ficheiros e texto

O que iremos cobrir?
  • Como abrir um ficheiro.
  • como ler e escrever para um ficheiro aberto.
  • como fechar um ficheiro.
  • construindo um contador de palavras

Lidar com ficheiros geralmente costuma significar uma tremenda dor de cabeça para os novatos, mas o que eu não consigo perceber é o porquê. Ficheiros na programação não são de forma alguma diferentes dos ficheiros que usas no te processador de texto ou em qualquer outra aplicação: tu abres um ficheiro depois, fazes o que tiveres de fazer depois, fechas o ficheiro. Simples heh!.

Pode-se dizer que grandes diferenças são que, na programação quando abres um ficheiro, abres o ficheiro sequencialmente, isto significa que les apenas uma linha de cada vez. Na prática o teu processador de texto na maior parte das vezes faz exactamente o mesmo, ele abre um ficheiro por completo e guarda-o na numa morada na memória enquanto tu trabalhas com ele, depois quando acabas, ele volta a escrever tido para a memória outra vez. A outra diferença é que quando abres um ficheiro só o podes abrir como de leitura, ou como de escrita. Tu podes escrever um ficheiro ao criar um novo (ou então escrevendo por cima de um outro já existente) ou então adicionando a um ficheiro já existente.

uma outra coisa que podes fazer enquanto estas a processar um ficheiro é que podes sempre voltar ao inicio.

Ficheiros - Input e Output

Agora vamos por em pratica tudo isto que estivemos a falar até agora. Vamos assumir que já existe um ficheiro chamado menu.txt, e que dentro desse ficheiro existe uma lista de refeições (um menu):

Bacalhau com natas 
Bacalhau à Gomez Sá 
Bacalhau com grão

Agora iremos criar um programa que irá ler esse ficheiro e depois exibir o seu conteúdo - como o comando 'cat' no Unix ou o comando 'Type' do DOS.

# Primeiro abrimos o ficheiro como de leitura(r)
inp = open("menu.txt","r")
# lê-se o conteúdo do ficheiro, transportando-o depois para dentro de uma lista 
# dispõem-se o conteudo dessa lista
for line in inp.readlines():
    print line
# Agora fechamos esse ficheiro 
inp.close()

Nota 1: open() São necessários 2 argumentos para este comando. O primeiro será o nome do ficheiro (que poderá ser passado como uma variável ou como uma string literal, como nó acabamos de fazer). O segundo é o modo. O modo determina como estamos a abrir o ficheiro, se só para leitura(r), ou se só para escrita(w), ainda podemos levar em consideração se o ficheiro será para aberto como texto ASCII ou para leitura binária - para fazer isso adicionamos um 'b' ao 'w' ou ao 'r', ficando: open (nomedoficheiro, "rb")

Note 2: Nós abrimos o ficheiro para ler o seu conteúdo e o fechamos usando funções precedidas pela variável do ficheiro. Este método é conhecido método da invocação, e é a nossa primeira espreitada em programação orientada a objectos. Mas não penses nisso por agora, mantém em mente apenas, que é uma coisa relacionada com os módulos. Poderás imaginar as variáveis do ficheiros como umas referências aos módulos contendo funções que operam sobre os ficheiros, funções essas que nós automaticamente importamos cada vez que criamos uma variável de um ficheiro.

Agora vamos considerar como podemos lidar com ficheiros extensos. em primerio lugar irias precisar de de ler no ficheiro uma linha de cada vez ( no Python) isso é conseguido utilizando o readline() em vez do readlines(). Poderás depois usar uma variável que irá contado as linhas e que irá aumentando a medida que cada linha é testada para ver se o seu valor é maior: que 25 (25 referente a linha do ecrã). Em caso que o resultado seja verdadeiro, poderás criar um comando que irá questionar o utilizador para carregar numa tecla (enter por exemplo) para fazer um reset e levar o contador de volta ao 0 e depois começar tudo de novo. Poderás querer tentar isso como um exercício.

E pronto, penso que é tudo. Abre-se um ficheiro, lês e manipulas os dados da forma que mais te convém, quando acabares fechas o ficheiro. Para criar um comando de cópia com Python, simplesmente abrimos um ficheiro novo em modo de escrita e escrevemos as linhas nesse ficheiro em vez de estarmos a dispôr no ecrã. Como neste exemplo que se segue:

# Vamos criar o equivalente ao: COPY MENU.TXT MENU.BAK

# primeiro vamos abrir os ficheiros para leitura(r) e escrita (w)
inp = open("menu.txt","r")
outp = open("menu.bak","w")

# ler o ficheiro e coloca-lo dentro de uma lista e depois 
# copia-lo para um novo ficheiro
for line in inp.readlines():
    outp.write(line)

print "1 ficheiro copiado..."

#agora fechamos os ficheiros
inp.close()
outp.close()

Não sei se reparaste que adicionei um comando 'print', isto foi apenas uma forma de assegurar ao utilizador que algo realmente aconteceu. Este tipo de feedback é sempre uma boa ideia quando falamos de programação.

Em tom de finalização, existem vezes que poderás apenas adicionar dados a um ficheiro já existente mas sem apagares os dados que esse ficheiro já contém. Uma forma de fazer isso, seria abrir abrires o ficheiro para escrita, mas antes copiavas todos os dados desse ficheiro para a lista, depois passarias todos os dados dessa lista para dentro do ficheiro mais um vez, criando assim uma nova versão do ficheiro. Quando é um ficheiro pequeno, este processo não trará problemas nenhum, mas se estivermos a falar de ficheiros muito grandes como por exemplo mais de 100Mb, então o que poderá acontecer é simplesmente ficas sem memória para levar o processo adiante. Felizmente existe um outro modo para abrir ficheiros, o "a" que quando utilizado com o open() permite-nos adicionar dados directamente directamente ao ficheiro sem apagar os dados que já lá estão. Melhor ainda, quando utilizas o "a" e o ficheiro especificado não existe, ele irá criar um novo ficheiro com o nome indicado e passará os dados para esse ficheiro.

Como exemplo, vamos assumir que temos um ficheiro que utilizamos para capturar as mensagens de erro. Mas não queremos apagar as mensagens de erro que lá estão contidas, então adicionamos as novas mensagens de erro assim:

def logError(msg):
   err = open("Errors.log","a")
   err.write(msg)
   err.close()

Na realidade muito provavelmente iríamos querer limitar o tamanho desse ficheiro de alguma forma. Uma técnica muito utilizada é criar um ficheiro baseado na data. Então o que acontece quando a data muda automaticamente cria-se um ficheiro novo, tornado assim mais fácil a localização de erros de um dia em particular e em geral a manutenção desses próprios ficheiros.

Contando palavras

Agora vamos visitar aquele programa para contar, que mencionei na secção anterior. Lembras-te que o pseudo-código tinha este aspecto:

def numwords(s):
    list = split(s) # uma lista em que cada elemento seria uma palavra
    return len(list) # iria dizer o número de elementos da lista

for linha in ficheiro:
    total = total + numwords(linha) # acumular os totais por linha
print "o ficheiro tinha %d palavras" % total

Agora que já sabemos como contar as linhas de um ficheiro, vamos ver o que acontece com o função numwords(). O que queremos fazer em primeiro lugar é criar uma lista uma lista que contém o numero de palavras numa linha. Se formos a procura na documentação do Python pelo modulo string, lá iremos dar de caras com uma função chamada split, o que essa função faz é contar as palavras.

O código final teria este aspecto:

import string
def numwords(s):
    list = string.split(s) # e preciso preceder o split pelo nome do módulo
    return len(list) # retorma o número de elementos na lista

inp = open("menu.txt","r")
total = 0  # inicia o total a zero

for linha in inp.readlines():
    total = total + numwords(line) # acumula os totais por linha
print "Ficheiro tinha %d palvras" % total

inp.close()

Isto não esta lá muito certo porque ele conta o caracter '&' como uma palavra (mas há também quem pense que assim é que esta correcto). Esta função podes ser usada para um ficheiro inteiro (menu.txt, por exemplo). Podes ainda fazer uns outros truques como o de perguntar ao utilizador qual o ficheiro que ele deseja copiar ou adicionar itens, isso através do raw_input e do argv, coisas que já vimos em capítulos anteriores.

BASIC e o Tcl

Tanto o BASIC como o Tcl, ambos têm as suas próprias formas de lidar com ficheiros. Que por ventura não são tão diferentes dos mecanismos utilizados pelo Python, Portanto irei por e simplesmente mostrar como funciona o programa 'cat' em cada um deles e não mais.

A versão do BASIC

O BASIC usa o conceito chamado streams para identificar os ficheiros. Estes streams são numerados o que pode tornar a lida com ficheiros um processo bastante monótono no BASIC. Isto pode ser evitado usando uma função chamada ???, que quando utilizada dá-nos o número do do stream disponível. Se guardares essa função numa variável, isso pode-te poupar muitas dores de cabeça e confusão em saber qual o número do stream/ficheiro.

INFILE = FREEFILE
OPEN "TEST.DAT" FOR INPUT AS INFILE
REM procura pelo fim do ficheiro EOF
REM depois lê o conteudo e imprime
DO WHILE NOT EOF(INFILE)
    LINE INPUT #INFILE, theLine
    PRINT theLine
CLOSE #INFILE

Versão do Tcl

Por estas alturas o padrão  utilizado já deve ser suficientemente claro, portanto aqui tens a versão do Tcl:

set infile [open "Test.dat" r]
while { [gets $infile line] >= 0} {
     puts $line
     }
close $infile
Pontos a lembrar
  • Tens que abrir os ficheiros antes de os poderes utiliza-los
  • Ficheiros normalmente só podem ser abertos como de leitura ou como para escrita, mas nunca com os dois modos em simultâneo
  • A função readlines() do Python lê todas as linhas de um ficheiro, enquanto o readline() só lê uma linha de cada vez o que pode ser muito útil quando tens problemas de memória.
  • Fecha sempre os ficheiros depois de os utilizares.
Anterior  Próximo  Índice


Em caso que tenhas alguma dúvida ou queiras comentar esta página envia-me um e-mail para: babyboy@oninet.pt