C++: Operações Avançadas com Arquivos
Última atualização: 2026-08-26
Na lição 40 aprendemos sobre tratamento de exceções.
Agora, vamos mergulhar nas operações com arquivos — uma habilidade essencial para persistência de dados em programas.
Sejam arquivos de configuração, logs ou bancos de dados, as operações com arquivos são indispensáveis.
1. Visão Geral dos Fluxos de Arquivo
(1) 1.1 Três Classes de Fluxo de Arquivo
O C++ usa três classes para manipular arquivos:
| Classe | Finalidade |
|---|---|
std::ifstream |
Fluxo de arquivo de entrada (leitura de arquivos) |
std::ofstream |
Fluxo de arquivo de saída (escrita de arquivos) |
std::fstream |
Fluxo de arquivo de entrada/saída (leitura e escrita) |
(2) 1.2 Abrindo um Arquivo
Exemplo: Abrindo um arquivo (Dificuldade ⭐)
▶ Exemplo 2: Demonstração de Operação com Arquivo (Dificuldade ⭐)
#include <iostream>
#include <fstream>
int main() {
std::ifstream file("data.txt");
if (!file) {
std::cerr << "Unable to open file" << std::endl;
return 1;
}
std::cout << "File opened successfully" << std::endl;
file.close();
return 0;
}
Saída:
File opened successfully
2. Leitura e Escrita de Arquivos de Texto
(1) 2.1 Lendo Linha por Linha
Exemplo: Contando linhas de um arquivo (Dificuldade ⭐)
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream file("data.txt");
std::string line;
int count = 0;
while (std::getline(file, line)) {
count++;
}
std::cout << "Number of lines: " << count << std::endl;
file.close();
return 0;
}
(2) 2.2 Leitura e Escrita Formatada
Exemplo: Lendo e escrevendo uma struct (Dificuldade ⭐⭐)
#include <iostream>
#include <fstream>
struct Student {
char name[50];
int age;
double score;
};
int main() {
Student s = {"Zhang San", 20, 85.5};
// Write to file
std::ofstream out("student.txt");
out << s.name << std::endl;
out << s.age << std::endl;
out << s.score << std::endl;
out.close();
// Read from file
Student s2;
std::ifstream in("student.txt");
in >> s2.name >> s2.age >> s2.score;
in.close();
std::cout << "Name: " << s2.name << std::endl;
std::cout << "Age: " << s2.age << std::endl;
std::cout << "Score: " << s2.score << std::endl;
return 0;
}
⚠️ Aviso:
- Esta abordagem não funciona bem para nomes com espaços (
>>para em espaços em branco)
3. Arquivos Binários
(1) 3.1 Por que Usar Arquivos Binários?
| Comparação | Arquivo de Texto | Arquivo Binário |
|---|---|---|
| Legibilidade | Legível por humanos | Não legível |
| Tamanho | Maior | Pequeno |
| Velocidade | Mais lento | Rápido |
| Multiplataforma | Boa | Ruim (problemas de endianidade) |
(2) 3.2 Lendo e Escrevendo Arquivos Binários
Exemplo: Leitura/escrita binária de uma struct (Dificuldade ⭐⭐⭐)
#include <iostream>
#include <fstream>
struct Student {
char name[50];
int age;
double score;
};
int main() {
Student s = {"Zhang San", 20, 85.5};
// Write binary file
std::ofstream out("student.bin", std::ios::binary);
out.write(reinterpret_cast<char*>(&s), sizeof(s));
out.close();
// Read binary file
Student s2;
std::ifstream in("student.bin", std::ios::binary);
in.read(reinterpret_cast<char*>(&s2), sizeof(s2));
in.close();
std::cout << "Name: " << s2.name << std::endl;
std::cout << "Age: " << s2.age << std::endl;
std::cout << "Score: " << s2.score << std::endl;
return 0;
}
💡 Dica:
- Use
writeereadpara E/S binária - Você deve especificar o número de bytes (
sizeof)
4. Acesso Aleatório
(1) 4.1 seekg e seekp
Acesso aleatório permite que você salte para qualquer posição em um arquivo para leitura ou escrita.
| Função | Finalidade |
|---|---|
seekg(pos) |
Definir posição de leitura |
seekp(pos) |
Definir posição de escrita |
tellg() |
Obter posição de leitura atual |
tellp() |
Obter posição de escrita atual |
(2) 4.2 Exemplo: Modificando conteúdo no meio de um arquivo (Dificuldade ⭐⭐⭐)
#include <iostream>
#include <fstream>
int main() {
std::fstream file("data.txt", std::ios::in | std::ios::out);
// Jump to the 10th byte
file.seekp(10);
// Write data (overwrite)
file << "Hello";
file.close();
return 0;
}
Saída:
Hello, File!
C++ File Operations
5. Estado do Fluxo de Arquivo
(1) 5.1 Flags de Estado
Fluxos de arquivo possuem 4 flags de estado:
| Flag | Descrição |
|---|---|
good() |
Está tudo bem |
eof() |
Atingiu o final do arquivo |
fail() |
Erro lógico (por exemplo, incompatibilidade de tipo) |
bad() |
Erro sério (por exemplo, falha no disco) |
(2) 5.2 Limpando o Estado
Exemplo: Tratando o final do arquivo (Dificuldade ⭐)
#include <iostream>
#include <fstream>
int main() {
std::ifstream file("data.txt");
std::string line;
while (true) {
std::getline(file, line);
if (file.eof()) {
break; // Reached end of file
}
std::cout << line << std::endl;
}
file.clear(); // Clear state to continue using
file.close();
return 0;
}
6. Prática: Banco de Dados Simples
▶ Exemplo 1: Gerenciamento de Registros de Estudantes (Dificuldade ⭐⭐⭐)
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
struct Student {
int id;
char name[50];
int age;
};
void saveStudents(const std::vectorStudent& students, const std::string& filename) {
std::ofstream file(filename, std::ios::binary);
for (const auto& s : students) {
file.write(reinterpret_cast<const char*>(&s), sizeof(s));
}
}
void loadStudents(std::vectorStudent& students, const std::string& filename) {
std::ifstream file(filename, std::ios::binary);
Student s;
while (file.read(reinterpret_cast<char*>(&s), sizeof(s))) {
students.push_back(s);
}
}
int main() {
std::vector<Student> students = {
{1, "Zhang San", 20},
{2, "Li Si", 21}
};
// Save
saveStudents(students, "students.bin");
// Load
std::vectorStudent loaded;
loadStudents(loaded, "students.bin");
std::cout << "Loaded " << loaded.size() << " records" << std::endl;
return 0;
}
Saída:
Loaded 2 records
▶ Exemplo 3: Leitura/Escrita Simples de Arquivo (Dificuldade ⭐)
#include <iostream>
#include <fstream>
#include <string>
int main() {
// Write to file
std::ofstream outFile("test.txt");
outFile << "Hello, File!" << std::endl;
outFile << "C++ File Operations" << std::endl;
outFile.close();
// Read from file
std::ifstream inFile("test.txt");
std::string line;
while (std::getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
return 0;
}
Saída:
(program output)
Saída esperada:
Hello, File!
C++ File Operations
❓ Perguntas Frequentes
P: Qual é melhor — arquivos de texto ou arquivos binários? R: Depende das suas necessidades: - Precisa de legibilidade humana → arquivos de texto - Precisa de desempenho/eficiência de espaço → arquivos binários - Precisa de compatibilidade multiplataforma → arquivos de texto
P: Como lidar com caracteres especiais/acentuados? R: O C++ tem suporte ruim para Unicode. Sugestões: - Salve arquivos de texto em codificação UTF-8 - Use bibliotecas de terceiros (como iconv) - Ou limite-se a inglês/apenas ASCII
P: E se um arquivo não puder ser aberto? R: Verifique com
if (!file), combinado com tratamento de exceções.
📖 Resumo
| Tópico | Pontos-chave |
|---|---|
| Classes de fluxo de arquivo | ifstream/ofstream/fstream |
| Arquivos de texto | Operadores << e >> |
| Arquivos binários | write e read |
| Acesso aleatório | seekg/seekp |
| Verificação de estado | eof()/fail()/bad() |
📝 Exercícios
-
Básico (Dificuldade ⭐): Use
ofstreampara escrever um arquivo de texto (três linhas de conteúdo), depois useifstreampara ler e exibir na tela. -
Intermediário (Dificuldade ⭐⭐): Use
fstreampara abrir um arquivo no modoios::binary, escreva um array de structs, depois leia e verifique. -
Desafio (Dificuldade ⭐⭐⭐): Use
seekg/tellgpara implementar acesso aleatório a arquivos. Crie um "arquivo de índice" que registra a posição de cada registro, suportando saltos diretos para um registro especificado pelo índice.
- Fluxos de arquivo: ifstream para leitura / ofstream para escrita / fstream para ambos
- Modos de abertura: in/out/app/binary/trunc
- Verificação de estado de arquivo: is_open/good/fail/eof
- Arquivos de texto vs arquivos binários: texto é legível mas mais lento
- Acesso aleatório: seekg/tellg para posicionar locais de leitura/escrita
Próxima lição: Expressões Regulares (#42)