Leitura e escrita de arquivos texto
1. Introdução aos Arquivos Texto em C
1.1. O que são arquivos texto
Arquivos texto são arquivos que armazenam dados legíveis por humanos, organizados em linhas separadas pelo caractere de nova linha (\n). Diferentemente dos arquivos binários, que armazenam dados em formato bruto (bytes sem interpretação), os arquivos texto podem ser abertos e visualizados em qualquer editor de texto simples. A terminação de linha varia entre sistemas operacionais: \n no Linux/macOS, \r\n no Windows, mas a biblioteca padrão do C trata essa diferença automaticamente no modo texto.
1.2. Ponteiro FILE* e a biblioteca <stdio.h>
Toda operação com arquivos em C utiliza um ponteiro do tipo FILE*, que é uma estrutura opaca definida em <stdio.h>. Esse ponteiro gerencia o buffer, a posição atual no arquivo e o modo de acesso. Incluir <stdio.h> é obrigatório para usar funções como fopen(), fclose(), fprintf(), fscanf(), entre outras.
1.3. Modos de abertura para texto
A função fopen() aceita um segundo parâmetro que define o modo de abertura. Para arquivos texto, os modos principais são:
"r"— leitura (arquivo precisa existir)"w"— escrita (cria ou sobrescreve)"a"— anexar (cria se não existir, escreve ao final)"r+"— leitura e escrita (arquivo precisa existir)"w+"— leitura e escrita (cria ou sobrescreve)"a+"— leitura e anexar (cria se não existir)
2. Abrindo e Fechando Arquivos Texto
2.1. Função fopen()
A sintaxe é FILE *fopen(const char *nome_arquivo, const char *modo). Ela retorna um ponteiro para FILE em caso de sucesso ou NULL em caso de erro (arquivo inexistente, permissão negada, etc.). Sempre verifique o retorno.
FILE *arquivo = fopen("dados.txt", "r");
if (arquivo == NULL) {
perror("Erro ao abrir arquivo");
return 1;
}
2.2. Função fclose()
int fclose(FILE *stream) fecha o arquivo, libera buffers e recursos do sistema. Retorna 0 em sucesso ou EOF em erro. Nunca esqueça de fechar o arquivo, especialmente em programas que abrem muitos arquivos.
if (fclose(arquivo) != 0) {
perror("Erro ao fechar arquivo");
}
2.3. Exemplo prático: abrir, verificar erro e fechar
#include <stdio.h>
int main() {
FILE *fp = fopen("exemplo.txt", "r");
if (fp == NULL) {
perror("fopen");
return 1;
}
printf("Arquivo aberto com sucesso!\n");
fclose(fp);
return 0;
}
3. Escrita em Arquivos Texto
3.1. Função fprintf()
Funciona como printf(), mas escreve no arquivo. Aceita os mesmos especificadores de formato: %s, %d, %f, %c, etc.
FILE *fp = fopen("saida.txt", "w");
if (fp == NULL) { perror("fopen"); return 1; }
fprintf(fp, "Nome: %s, Idade: %d, Altura: %.2f\n", "Maria", 30, 1.75);
fclose(fp);
3.2. Função fputs()
Escreve uma string sem formatação adicional. Não adiciona quebra de linha automaticamente.
fputs("Primeira linha\n", fp);
fputs("Segunda linha\n", fp);
3.3. Função fputc()
Escreve um único caractere. Útil para escrever caractere por caractere, como em buffers processados.
char c = 'A';
fputc(c, fp);
4. Leitura de Arquivos Texto
4.1. Função fscanf()
Lê dados formatados do arquivo. Requer cuidado com espaços e buffers: especificadores como %s param no primeiro espaço em branco.
char nome[50];
int idade;
FILE *fp = fopen("dados.txt", "r");
if (fp == NULL) { perror("fopen"); return 1; }
fscanf(fp, "%s %d", nome, &idade); // Lê até espaço
printf("Nome: %s, Idade: %d\n", nome, idade);
fclose(fp);
4.2. Função fgets()
Lê uma linha completa (incluindo o \n) até encontrar nova linha ou o tamanho máximo do buffer. É a função mais segura para leitura de linhas.
char linha[100];
while (fgets(linha, sizeof(linha), fp) != NULL) {
printf("Linha lida: %s", linha);
}
4.3. Função fgetc()
Lê um caractere por vez. Retorna o caractere como int (para permitir EOF). Útil para processamento caractere a caractere.
int c;
while ((c = fgetc(fp)) != EOF) {
putchar(c); // ou processa de outra forma
}
5. Navegação e Controle de Fluxo
5.1. Função feof()
Retorna verdadeiro se o indicador de fim de arquivo estiver ativo. Cuidado: só é ativado após uma tentativa de leitura que encontra o fim.
while (!feof(fp)) {
// leitura aqui
}
5.2. Função ferror()
Retorna verdadeiro se ocorreu um erro na última operação de leitura/escrita.
if (ferror(fp)) {
printf("Erro durante operacao no arquivo\n");
}
5.3. Funções rewind() e fseek()
rewind(fp) volta ao início do arquivo. fseek(fp, deslocamento, origem) permite posicionar em qualquer ponto (útil para arquivos texto estruturados com registros de tamanho fixo).
rewind(fp); // volta ao início
fseek(fp, 0, SEEK_END); // vai para o final
6. Exemplos Práticos e Boas Práticas
6.1. Exemplo 1: copiar conteúdo de um arquivo texto para outro
#include <stdio.h>
int main() {
FILE *origem = fopen("origem.txt", "r");
FILE *destino = fopen("destino.txt", "w");
char linha[256];
if (origem == NULL || destino == NULL) {
perror("Erro ao abrir arquivos");
return 1;
}
while (fgets(linha, sizeof(linha), origem) != NULL) {
fputs(linha, destino);
}
fclose(origem);
fclose(destino);
return 0;
}
6.2. Exemplo 2: ler números de um arquivo e calcular soma/média
#include <stdio.h>
int main() {
FILE *fp = fopen("numeros.txt", "r");
int numero, soma = 0, count = 0;
if (fp == NULL) { perror("fopen"); return 1; }
while (fscanf(fp, "%d", &numero) == 1) {
soma += numero;
count++;
}
if (count > 0) {
printf("Soma: %d, Media: %.2f\n", soma, (float)soma / count);
} else {
printf("Nenhum numero encontrado.\n");
}
fclose(fp);
return 0;
}
6.3. Boas práticas
- Sempre verifique o retorno de
fopen(),fscanf(),fgets(). - Use
fgets()em vez defscanf()para leitura de textos não estruturados. - Defina buffers com tamanho adequado para evitar estouro.
- Feche todos os arquivos abertos, mesmo em caso de erro.
7. Tratamento de Erros e Casos Especiais
7.1. Arquivos inexistentes ou sem permissão
Sempre trate o retorno NULL de fopen():
FILE *fp = fopen("config.txt", "r");
if (fp == NULL) {
printf("Arquivo nao encontrado ou sem permissao.\n");
return 1;
}
7.2. Linhas muito longas
Se uma linha exceder o tamanho do buffer de fgets(), a leitura será parcial. Para linhas dinâmicas, use alocação com getline() (POSIX) ou leia caractere por caractere com fgetc().
7.3. Codificação de caracteres
Arquivos texto em C tratam bytes. Para UTF-8, use setlocale(LC_ALL, "pt_BR.UTF-8") no início do programa para que funções como fprintf() respeitem caracteres acentuados.
#include <locale.h>
setlocale(LC_ALL, "pt_BR.UTF-8");
Referências
- Documentação oficial da GNU C Library: Arquivos — Referência completa sobre operações de arquivo na glibc, incluindo modos de abertura e funções de leitura/escrita.
- cppreference.com: File input/output — Documentação detalhada de todas as funções de E/S em C, com exemplos e notas sobre comportamento.
- Tutorial da IBM: Manipulação de arquivos em C — Guia prático sobre fopen, fclose, fprintf, fscanf e tratamento de erros.
- GeeksforGeeks: File Handling in C — Tutorial introdutório com exemplos de leitura e escrita de arquivos texto, incluindo fgets e fputs.
- Stack Overflow: Como ler arquivos texto linha por linha em C — Discussão técnica sobre as melhores práticas para leitura de linhas, incluindo fgets vs fscanf.
- Tutorial da UFRGS: Arquivos em linguagem C — Material acadêmico completo sobre manipulação de arquivos texto e binários em C, com exemplos comentados.