HomePage RecentChanges

Lesson20

Todos os programas que vimos até agora obtêm dados do standard input, por exemplo caracteres introduzidos no teclado durante uma interacção, e enviam dados para o standard output, por exemplo sequência de caracteres mostradas no ecrã. Quando um programa termina, todos os dados utilizados pelo mesmo desaparecem e não os podemos recuperar.

No entanto a maior parte dos programas que utilizamos nos nossos computadores mantêm estado, ou seja, quando voltamos a executá-los podemos continuar onde ficámos numa utilização anterior, e por outro lado podemos fazer uso de várias fontes e destinos de dados. Neste caso diz-se que temos dados persistentes no sentido que estes perduram independentemente da execução do programa, sendo guardados num disco rígido, numa directoria partilhada, num sistema de armazenamento online, etc. Em qualquer caso um destes casos, os dados são em geral armazenados em ficheiros.

Veremos nesta aula como trabalhar com ficheiros.

Um ficheiro tem alguns aspectos particulares:

  1. podem existir independentemente de qualquer programa;
  2. durante a execução de um programa, um ficheiro pode estar num de dois estados, em modo de leitura (em que estamos a ler valores do mesmo) ou em modo de escrita (em que estamos a escrever valores no mesmo).

Os ficheiros existem fisicamente num sistema de ficheiros, em geral organizados em directorias. Quando queremos utilizar um ficheiro temos de indicar a sua localização física. É importante notar que a especificação da localização varia, por exemplo, consoante o sistema operativo que estamos a utilizar e/ou se o ficheiro está numa localização local ou remota.

O tipo ficheiro

Dada a localização física do ficheiro em que estamos interessados, e modo como queremos aceder ao mesmo, temos de realizar uma operação de abertura do ficheiro. Em Python recorremos então à função pré-definida open, com a seguinte sintaxe

open(<expressão>, <modo>{, encoding = <tipo>})

em que os dois primeiros argumentos são obrigatórios e o último é opcional:

<modo> ::= 'r' | 'w' | 'a'

denotando a abertura para leitura ("read"), escrita ("write") e escrita a partir do final do ficheiro ("append"), respectivamente;

O resultado da operação open é o valor que corresponde à identidade associada ao ficheiro.

Leitura

Quando abrimos um ficheiro para leitura está subentendido que esse ficheiro existe. Caso o ficheiro não exista, será gerado um erro.

>>> open('nofile.txt', 'r')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'nofile.txt'
>>>

Vamos assumir que temos o ficheiro teste.txt na directoria em que estamos a trabalhar, ou seja, na directoria actual, com o seguinte conteúdo:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi quis
dui at lectus ornare pulvinar. Curabitur eu lacinia lacus. Morbi ac
dui nec magna aliquet sagittis sit amet sed justo. Nulla mattis nisi
et orci tincidunt, ac vulputate nisl pretium. Praesent vel orci eget mi
pulvinar ullamcorper. Ut eu nibh sit amet leo efficitur laoreet. Nullam
non libero euismod dui pretium tempus. Nullam tincidunt suscipit diam,
bibendum pharetra felis accumsan ac. Pellentesque pulvinar posuere odio
id congue. Integer efficitur velit a tincidunt pellentesque. Cras quis
odio euismod, ornare elit at, facilisis libero. Sed semper augue sed
fringilla rhoncus. Proin ut leo ante. Nullam ac urna vel orci viverra
tempor. Etiam sagittis justo erat, ut tempor orci fringilla quis.

Para abrir o ficheiro podemos fazer o seguinte, assumindo que o ficheiro está codificado em UTF-16,

>>> f = open('teste.txt', 'r', encoding = 'UTF-16')
>>> f
<_io.TextIOWrapper name='teste.txt' mode='r' encoding='UTF-16'>
>>>

Em geral os ficheiros são lidos de forma sequencial e é utilizado internamente (pelo Python no nosso caso) um indicador de leitura que indica o próximo elemento a ser lido. No caso de um ficheiro aberto para leitura, este indicador é inicializado no primeiro elemento do ficheiro e desloca-se a cada leitura para o final do ficheiro.

Uma vez o ficheiro <file> aberto para leitura, podemos efectuar algumas operações sobre o mesmo:

Exemplo:

>>> f = open('teste.txt', 'r')
>>> l = f.readline()
>>> l
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi quis\n'
>>> ll = f.readlines()
>>> ll
['dui at lectus ornare pulvinar. Curabitur eu lacinia lacus. Morbi ac\n', 'dui nec magna aliquet sagittis sit amet sed justo. Nulla mattis nisi\n', 'et orci tincidunt, ac vulputate nisl pretium. Praesent vel orci eget mi\n', 'pulvinar ullamcorper. Ut eu nibh sit amet leo efficitur laoreet. Nullam\n', 'non libero euismod dui pretium tempus. Nullam tincidunt suscipit diam,\n', 'bibendum pharetra felis accumsan ac. Pellentesque pulvinar posuere odio\n', 'id congue. Integer efficitur velit a tincidunt pellentesque. Cras quis\n', 'odio euismod, ornare elit at, facilisis libero. Sed semper augue sed\n', 'fringilla rhoncus. Proin ut leo ante. Nullam ac urna vel orci viverra\n', 'tempor. Etiam sagittis justo erat, ut tempor orci fringilla quis.\n']
>>> f.read()
''
>>> f.close()
>>> f = open('teste.txt', 'r')
>>> f.read()
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi quis\ndui at lectus ornare pulvinar. Curabitur eu lacinia lacus. Morbi ac\ndui nec magna aliquet sagittis sit amet sed justo. Nulla mattis nisi\net orci tincidunt, ac vulputate nisl pretium. Praesent vel orci eget mi\npulvinar ullamcorper. Ut eu nibh sit amet leo efficitur laoreet. Nullam\nnon libero euismod dui pretium tempus. Nullam tincidunt suscipit diam,\nbibendum pharetra felis accumsan ac. Pellentesque pulvinar posuere odio\nid congue. Integer efficitur velit a tincidunt pellentesque. Cras quis\nodio euismod, ornare elit at, facilisis libero. Sed semper augue sed\nfringilla rhoncus. Proin ut leo ante. Nullam ac urna vel orci viverra\ntempor. Etiam sagittis justo erat, ut tempor orci fringilla quis.\n'
>>> f.read()
''
>>> f.seek(0)
0
>>> f.read()
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi quis\ndui at lectus ornare pulvinar. Curabitur eu lacinia lacus. Morbi ac\ndui nec magna aliquet sagittis sit amet sed justo. Nulla mattis nisi\net orci tincidunt, ac vulputate nisl pretium. Praesent vel orci eget mi\npulvinar ullamcorper. Ut eu nibh sit amet leo efficitur laoreet. Nullam\nnon libero euismod dui pretium tempus. Nullam tincidunt suscipit diam,\nbibendum pharetra felis accumsan ac. Pellentesque pulvinar posuere odio\nid congue. Integer efficitur velit a tincidunt pellentesque. Cras quis\nodio euismod, ornare elit at, facilisis libero. Sed semper augue sed\nfringilla rhoncus. Proin ut leo ante. Nullam ac urna vel orci viverra\ntempor. Etiam sagittis justo erat, ut tempor orci fringilla quis.\n'
>>> f.close()
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.

Como vimos em aulas anteriores, é importante ter em conta as várias codificações possíveis para os caracteres, as diferentes formas de terminar linhas e que podem variar de sistema operativo para sistema operativo, e também a diferentes formas de especificar as localizações dos ficheiros dependendo também do sistema operativo e se são locais ou remotos.

Escrita

Neste caso temos de abrir o ficheiro em modo de escrita, 'w' ou 'a'. Se o ficheiro não existir, então é criado. Neste caso temos também um indicador denominado indicador de escrita, que indica a posição a posição onde será escrito o próximo elemento. Quando abrimos o ficheiro em modo 'w' ou 'a' o indicador de escrita é colocado no início ou no final do ficheiro, respectivamente. Nota-se que no modo 'w' o conteúdo do ficheiro é eliminado e perdido.

Uma vez o ficheiro <file> aberto para escrita, podemos efectuar algumas operações sobre o mesmo:

Exemplo:

>>> f = open('teste.txt', 'w')
>>> f.close()
>>> f = open('teste.txt', 'r')
>>> f.read()
''
>>> f.close()
>>> f = open('teste.txt', 'w')
>>> f.write('fundamentos de programacao')
26
>>> f.close()
>>> f = open('teste.txt', 'r')
>>> f.read()
'fundamentos de programacao'
>>> f.close()
>>> f = open('teste.txt', 'a')
>>> f.write('\n2015/16\n1o semestre\n')
21
>>> f.close()
>>> f = open('teste.txt', 'r')
>>> f.read()
'fundamentos de programacao\n2015/16\n1o semestre\n'
>>> f.seek(0)
0
>>> ll = f.readlines()
>>> f.close()
>>> f = open('teste.txt', 'a')
>>> f.writelines(ll)
>>> f.writelines(ll)
>>> f.close()
>>> f = open('teste.txt', 'r')
>>> f.read()
'fundamentos de programacao\n2015/16\n1o semestre\nfundamentos de programacao\n2015/16\n1o semestre\nfundamentos de programacao\n2015/16\n1o semestre\n'
>>> f.seek(0)
0
>>> print(f.read())
fundamentos de programacao
2015/16
1o semestre
fundamentos de programacao
2015/16
1o semestre
fundamentos de programacao
2015/16
1o semestre

>>> f.close()
>>>

Depois de aberto um ficheiro para escrita, podemos também utilizar a função print cuja sintaxe é na realidade definida como se segue:

<escrita de dados> ::=
    print() |
    print(file = <nome de ficheiro>) |
    print(<expressões>) | 
    print(<expressões>, file = <nome de ficheiro>)

<nome de ficheiro> ::= <nome>

Exemplo:

>>> f = open('teste.txt', 'w')
>>> f.write('fundamentos de programacao\n')
27
>>> print(2015, '/', 2016, file = f)
>>> f.close()
>>> f = open('teste.txt', 'r')
>>> print(f.read())
fundamentos de programacao
2015 / 2016

>>> f.close()
>>>

Notar que nesta aula considerámos apenas ficheiros de texto.