# Ficheiros e dados tabulares

Abrir e fechar ficheiros, modos de escrita, CSV, conversões e leitura reproduzível.

Página: https://resumos.rgo.pt/cadeiras/ct-iadp/ficheiros/

Um ficheiro mantém dados depois de o programa terminar. Ler transforma esses dados em objetos Python; escrever transforma objetos em bytes ou texto guardados. Confirma o caminho, a codificação e o formato antes de interpretar os valores.

## Abrir com um contexto

```
with open("vendas.txt", "r", encoding="utf-8") as ficheiro:
    texto = ficheiro.read()
```

`with` fecha o ficheiro quando sais do bloco, incluindo quando ocorre uma exceção. `read()` lê todo o texto; `read(n)` lê até n caracteres em modo texto ou n bytes em modo binário. `readline()` lê uma linha, normalmente conservando a mudança de linha. No fim do ficheiro, devolve uma string vazia; uma linha em branco pode conter `"\n"`. O iterador do ficheiro permite processar uma linha de cada vez. Sem `with`, chama `close()` quando terminares.

| Modo | Efeito |
| --- | --- |
| `"r"` | Lê um ficheiro existente |
| `"w"` | Cria ou substitui o conteúdo do ficheiro |
| `"a"` | Acrescenta ao fim |
| `"x"` | Cria e falha se já existir |
| `"rb"` | Lê bytes, sem descodificar texto |

`"w"` pode apagar conteúdo anterior. Para fazer uma experiência, escolhe um ficheiro de teste. O diretório de trabalho é a base dos caminhos relativos, não necessariamente a pasta onde está o script.

## Linhas e campos

Um ficheiro com duas linhas pode ter este conteúdo:

```
produto,quantidade,preco
pão,2,1.50
leite,3,1.20
```

Separar cada linha por vírgulas funciona neste exemplo, mas falha quando um campo contém uma vírgula entre aspas. Usa o módulo `csv`, que conhece essas regras.

```python
import csv
from io import StringIO

texto = 'produto,quantidade,preco\npão,2,1.50\nleite,3,1.20\n'
ficheiro = StringIO(texto)
total = 0
for linha in csv.DictReader(ficheiro):
    quantidade = int(linha["quantidade"])
    preco = float(linha["preco"])
    total += quantidade * preco
print(f"Faturação: {total:.2f} euros")
```

`StringIO` trata uma string como um ficheiro de texto em memória. Assim, o exemplo é reproduzível no navegador. O total é `2 × 1,50 + 3 × 1,20 = 6,60 euros`.

`DictReader` usa o cabeçalho para nomear as colunas, mas os campos continuam a ser strings. A conversão numérica faz parte da leitura. Se uma célula estiver vazia ou tiver `"n/a"`, decide como representar a ausência antes de converter.

Num ficheiro real, usa `open(..., newline="", encoding="utf-8")` com `csv`. `newline=""` deixa o módulo tratar as mudanças de linha. Se o separador for ponto e vírgula, passa `delimiter=";"`.

## Escrever resultados

```
import csv

with open("totais.csv", "w", newline="", encoding="utf-8") as ficheiro:
    escritor = csv.writer(ficheiro)
    escritor.writerow(["produto", "total"])
    escritor.writerows([["pão", 3.0], ["leite", 3.6]])
```

`ficheiro.write(texto)` escreve a string e devolve o número de caracteres escritos; não acrescenta automaticamente uma mudança de linha. Em modo binário, recebe bytes. O modo `"t"` é texto e `"b"` é binário; `"rt"` equivale à leitura de texto habitual.

A escrita CSV converte os valores para texto. Ao reler, os tipos não reaparecem por magia. Define os tipos esperados e o significado de cada coluna.

## O que conferir antes de calcular

Verifica se há cabeçalho, se cada linha tem o número de campos esperado e se a unidade é constante. Uma coluna pode guardar euros ou cêntimos; as duas contêm números, mas produzem totais diferentes por um fator de cem.

Para dados grandes, percorre as linhas sem as guardar todas. Para análise tabular com filtros, junções e agregações, a próxima parte usa pandas. A regra mantém-se: primeiro compreender a tabela, depois escolher a operação.

## Exercícios

Interpretar quantidades e preços

Um CSV tem duas vendas: 2 unidades a 1,50 euros e 3 unidades a 1,20 euros. Qual é a faturação em euros?

Primeira pista

Calcula quantidade vezes preço em cada linha.

Mais uma pista

As parcelas são 3,00 e 3,60.

Ver solução

A faturação é 6,60 euros. Converte os campos de texto para números antes de multiplicar.

#### Erros frequentes

Somar os preços unitários ou multiplicar strings.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/ficheiros/#linhas-e-campos)

Ler campos com aspas

Por que split(”,”) não é suficiente para ler uma linha CSV com um nome entre aspas que contém uma vírgula?

Primeira pista

CSV tem regras para aspas e separadores.

Mais uma pista

Uma separação literal não distingue a vírgula de um campo da vírgula entre campos.

Ver solução

O módulo csv interpreta aspas e escapes e mantém o nome num único campo. Depois da leitura, os valores numéricos ainda precisam de conversão.

Confere a tua resposta:

*   Identifiquei que a vírgula dentro das aspas pertence ao campo.
*   Escolhi csv.reader ou csv.DictReader.
*   Conservei a necessidade de converter os campos numéricos.

#### Erros frequentes

Afirmar que todo o CSV usa sempre vírgula ou que DictReader devolve automaticamente números.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/ficheiros/#linhas-e-campos)
