Aula 08 - Escrita e Leitura em Ficheiros - Introdução
Conceitos-Chave:
- fstream, biblioteca standard do C++ para leitura e escrita em ficheiros
- ofstream, para escrita em ficheiros
- ifstream, para leitura em ficheiros
- getline(), função para receber uma frase do utilizador (cin.getline) ou de um ficheiro (ifstream::getline)
Escrita e Leitura em Ficheiros
A leitura (e escrita) de ficheiros tornou-se essencial em programação de jogos, por exemplo na construção de mapas e para guardar o percurso do jogador no jogo.
Durante esta lição vamo-nos concentrar no básico da escrita e leitura
em ficheiros. O carregamento de mapas e tratamento de dados virá
depois.
Para podermos ter acesso à leitura (ou escrita) de ficheiros teremos que usar a biblioteca fstream (file stream). A melhor forma de explicar o básico da escrita/leitura em ficheiros é com um programa:
#include <iostream>
#include <fstream> //inclui a biblioteca fstream, para usar o ofstream e ifstream
using namespace std;
int main()
{
// para escrita a instrução é ofstream variavel("nome_do_ficheiro.txt)
ofstream doc_out("save.txt"); //abre o ficheiro save.txt para escrita
// para leitura a instrução é ifstream variavel("nome_do_ficheiro.txt)
ifstream doc_in("save.txt"); //abre o ficheiro save.txt para leitura
char aux[50]; //cria um array com capacidade para 50 caracteres
doc_out << "Nivel:1\n" << "Nick:Agnor" << endl;
doc_out.close(); //não se esqueçam de fechar os ficheiros de escrita!!!!
while (doc_in >> aux) //enquanto o conteúdo do documento não for transferido para o aux...
{
cout << aux << endl; //...imprime no ecrã as palavras.
}
//notem que o ficheiro de leitura não necessita de ser fechado
cin.get();
return 0;
}
Vamos por partes:
ofstream
ofstream significa output file stream e serve para a escrita em ficheiros. Antes de poder escrever alguma coisa, temos que definir em que ficheiro queremos guardar o texto: ofstream nome_da_variavel(nome_do_ficheiro). Tanto o ofstream e o ifstream pertencem à bilbioteca fstream, que tem de ser incluída no programa ( #include <fstream>). De notar que todos os ficheiros de escrita necessitam de ser fechados, quando não precisarmos mais deles (usando o close() ).
ifstream
ifstream serve para a leitura de ficheiros (input file stream). Define-se como a biblioteca ofstream: ifstream nome_da_variavel(nome_do_ficheiro)
Dica:
Para aceder a um ficheiro de texto que esteja dentro de uma pasta, temos de separar o nome da pasta do nome do ficheiro, através de uma barra '/'. Por exemplo: ofstream mapa("mapas/nivel1.map");
doc_out << string; e doc_in >> string;
Enviamos texto para um ficheiro da mesma forma que enviamos para o console output e lemos um ficheiro da mesma forma que o lemos através do console input. Neste exemplo:
doc_out << "Nivel:1" <<- estamos a enviar a string "Nivel:1" e o comando endl (para mudar de linha) para o doc_out, ou seja, para o ficheiro identificado por doc_out (save.txt).
doc_in >> aux - estamos a enviar o conteúdo de doc_in (apenas a primeira palavra) para a string aux.
doc_out.close()
Sempre que acabarmos de escrever no ficheiro, temos de fechá-lo. Para tal existe a função close() dentro da biblioteca fstream. Notem que é utilizado um '.' (ponto) para unir o doc_out à "função" close(). Isto será explicado quando falarmos de classes.
while (doc_in >> aux)
Como ao fazermos doc_in >> aux só é transferida a primeira palavra para o output, temos de criar um loop. A expressão (doc_in >> aux) vai ser verdadeira quando chegar ao fim do ficheiro. Então, enquanto não chegar ao fim do ficheiro, será executada o doc_in >> aux e será mostrado no cout o conteúdo de aux. Como cada vez que fazemos doc_in >> aux este avança para a palavra seguinte, é mostrado o conteúdo todo do ficheiro, palavra por palavra.
Usar cin.getline()
O uso de cin.getline() pode-vos parecer totalmente fora do assunto da lição, mas depois perceberão porque o pus aqui.
Até agora, já devem ter reparado que num programa que receba dados do utilizador através de cin (console input), só receberão uma palavra e não uma frase. O cin.getline() , como o próprio nome indica, recebe uma linha do utilizador. O protótipo da função é:
cin.getline(char *buffer, int length, char terminal_char);
O char *buffer será a string (conjunto de carácteres) onde será armazenado o
input, a lenght será o tamanho da string e o último será o carácter terminador. O carácter terminador está predefenido como \n ou seja, quando a frase acabar.
Devem notar que há um asterisco (*) antes da variável buffer. Isso
é uma declaração de um apontador (que será explorado na aula 11. O uso de apontadores (char* buffer) permite-nos criar uma string, sem que seja necessário definir um número de caracteres específicos
O último parâmetro é opcional, e na maior parte das vezes pode ser
ignorado. Vejam um exemplo de uso com a função:
#include <iostream>
using namespace std;
int main()
{
char nome[150]; //cria uma variável capaz de conter 150 caracteres
cout << "Insira o seu nome completo:" << endl;
cin.getline(nome, 150);
cout << "O seu nome e: " << nome << endl;
cin.get();
return 0;
}
Deve ser o suficiente para perceberem, no entanto qualquer dúvida e contactem-me.
Ler linhas de ficheiros
Para ler linhas em ficheiros a função é exactamente a mesma, só que aplicada de maneira diferente. Por exemplo:
ifstream doc_in("save.txt");
doc_in.getline(variavel, 200);
Difícil? Nem por isso :P
Sempre que usarmos a função getline(); o ficheiro avança para a próxima linha (em vez de avançar para a próxima palavra). Experimentem o código abaixo:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char aux[150]; //cria uma variável capaz de conter 150 caracteres, para a escrita
char boas_vindas[150];
char nome[150];
char idade[4]; //só contem 4 carácteres, não é preciso mais para a idade
//notem que é do tipo char e não int... um problema a ser explorado em aulas mais avançadas
ifstream doc_in("save.txt");
ofstream doc_out("save.txt");
doc_out << "Bemvindo ao Programa" << endl; /*a mensagem de boas-vindas não pode ser personalizada
pelo utilizador, mas só pelo programador*/
cout << "Insira o seu nome: " << endl;
cin.getline(aux, 150);
doc_out << aux << endl;
cout << "Insira a sua idade: " << endl;
cin >> aux;
doc_out << aux << endl;
doc_out.close(); //fecha o documento
doc_in.getline(boas_vindas, 150); //cada vez que faz a chamada à função muda-se de linha
doc_in.getline(nome, 150);
doc_in.getline(idade, 4);
cout << boas_vindas << " " << nome << ", " << idade << " anos" << endl;
system("PAUSE");
return 0;
}
Não necessita de muitas explicações. Há alguns problemas com este código que impedem de ser uma forma viável de salvar jogos, mas serão explorados (e resolvidos espero :) em futuras lições.
Um bom exercício seria separar o programa, criando uma versão que serviria somente para criar o ficheiro de texto, e outra para lê-lo, seria uma versão bastante primitiva de um editor de níveis.
Próxima aula -> C++ 09 - Leitura e Escrita em Ficheiros de Texto - Introdução
Fazer o download do código fonte dos exemplos da aula
Fazer o download da aula em PDF (Brevemente)
Ir para o topo da página