processamento de arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria...
TRANSCRIPT
Programação de Computadores 323
Processamento de Arquivos! Arquivos são usados para armazenar dados de forma
permanente;! São armazenados em dispositivos de armazenamento
secundário tais como, discos magnéticos e óticos, fitas, discos removíveis, etc.
! C++ enxerga um arquivo simplesmente como uma seqüência de bytes.
! Cada arquivo termina ou com uma marca de fim de arquivo ou tem um específico número de bytes (mantido e administrado pelo sistema)
! Quando um arquivo é aberto, um objeto é criado e uma stream é associada com o objeto.
...0 n-1...987654321
marca de fim de arquivo
Programação de Computadores 324
! Quatro objetos são criados automaticamente quando da inclusão de iostream.h: cin,cout, cerr, clog.
! Stream’s associadas com esses objetos fornecem um canal de comunicação entre o programa e um arquivo ou dispositivo: objeto cin" permite a comunicação via teclado; objeto cout" comunicação via vídeo; objetos cerr e clog " permitem que o programa escreva suas mensagens de erro na tela ou em outros dispositivos
! Para podermos realizar operações em arquivos temos que incluir: iostream.h e fstream.h" que inclui a definição das classes istream (entrada) e ostream (saída) " arquivos são abertos criando objetos dessas classes.
Programação de Computadores 325
! Existem dois tipos básicos de E/S em discos usando C++: formatado e binário.
! Formatado" os números são armazenados no disco como uma série de caracteres. ! 6.02 ao invés de ser armazenado como o tipo float, ou seja,
ocupando 4 bytes é armazenado como sendo os caracteres ‘6’, ‘.’, ‘0’, ‘2’.
! Pode ser ineficiente para números com muitos dígitos, mas é apropriado para muitas situações e muito fácil de implementar.
! O programa a seguir, escreve um caractere, um inteiro, um real e duas cadeias de caracteres num arquivo em disco chamado fdados.txt
Programação de Computadores 326
#include <fstream.h>#include <stdlib.h>void main( ){ char ch = 'x';
int j = 22;double d=98.7;
char str1[ ]= "Boa Tarde";char str2[ ] = "Bom Dia";ofstream arq_saida("fdados.txt“, ios::out);if (!arq_saida){ cout<<“arquivo não pode ser aberto:”<<endl;
exit(1);}
arq_saida<<ch<<j<<‘ ‘<<d<<str1<<‘ ‘<<str2;}
Programação de Computadores 327
! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para saída. Os argumentos “fdados.txt” (nome do arquivo) e ios::out (modo de abertura) são passados para o construtor da classe ofstream que abre o arquivo.
! Modos de aberturaios::app " escreve no final do arquivoios::in " abre o arquivo para leitura (padrão para ifstream)ios::out " abre para escrita (padrão para ofstream. Se o arquivo já
existir ele é reescrito)ios::ate " começa a leitura/escrita no final do arquivoios::binary " abre um arquivo no modo binário (não texto)ios::nocreate " sinaliza erro se o arquivo ainda não existeios::noreplace" sinaliza erro quando abre um arquivo para saída e
ele já existe, a menos que ate ou app estejam também escolhidos
Programação de Computadores 328
! Depois de aberto o programa testa se a operação teve sucesso (!arq_saida) " possíveis erros: tentativa de abrir para leitura um arquivo que não existe; tentativa de abrir um arquivo para escrita mas o disco está cheio, tentativa de abrir um arquivo sem permissão.
! Após o arquivo ter sido criado é possível ver seu conteúdo usando qualquer editor, como por exemplo o Notepad.
! O conteúdo pode ser recuperado, fazendo a leitura do arquivo através de um programa.
Programação de Computadores 329
#include <fstream.h>#include <stdlib.h>void main( ){ char ch ;int j ;double d;char str1[80],str2[80];ifstream arq_entrada("fdados.txt",ios::in);if (!arq_entrada){ cerr<<"arquivo não pode ser aberto"<<endl;
exit(1);}arq_entrada>>ch>>j>>d>>str1>>str2;cout<<endl<<"dados lidos do arquivo"<<endl
<<"ch="<<ch<<endl<<"j="<<j<<endl<<"d="<<d<<endl<<"str1="<<str1<<endl<<"str2="<<str2;
}
Programação de Computadores 330
! As cadeias escritas no arquivo, não podem conter o caractere branco, ou seja, não posso colocar cadeias do tipo “bom dia” , nem para str1 e str2. Isso ocorre porque o caractere delimitador de cadeia é o caractere branco.
! Usamos nesse caso a função getline( ) ao invés do operador de extração
! A seguir mostramos como escrever e ler um arquivo com cadeias de caracteres.
Programação de Computadores 331
#include <fstream.h>#include <stdlib.h>void main( ){ ofstream arq_saida("cadeias.txt", ios::out);if (!arq_saida){ cout<<"arquivo não pode ser aberto:"<<endl;
exit(1);}arq_saida<<"Eu canto porque o instante existe\n";arq_saida<<"E a minha vida está completa\n";arq_saida<<"Não sou alegre nem sou triste\n";arq_saida<<"Sou poeta\n";
}
Gravando o arquivo
Programação de Computadores 332
! Para lermos o arquivo precisamos conhecer alguns detalhes! Objetos derivados de ios contem bits que sinalizam
eventuais erros, que podem ser testados para determinarmos o resultado de uma operação.
! Quando lemos um arquivo do tipo que foi gravado pelo programa anterior, fazemos a leitura até encontrar a condição de fim de arquivo (EOF- end of file)" sinal enviado ao programa pelo hardware quando não existe mais dados para serem lidos.
! Construções que podem ser usadas para testar fim de arquivo: ! while (!arq_entrada.eof( )) // especificamente para eof! while (arq_entrada) // para qualquer erro encontrado
Programação de Computadores 333
#include <fstream.h>#include <stdlib.h>void main( ){ char buffer[80];ifstream arq_entrada("cadeias.txt");if (!arq_entrada){ cout<<"arquivo não pode ser aberto:"<<endl;
exit(1);}while (arq_entrada){ arq_entrada.getline(buffer, 80);
cout<<buffer<<endl;}
}
Programação de Computadores 334
! Funções put( ) e get( ) " usadas para entrada e saída de um único caractere.#include <fstream.h> // para usar arquivos#include <string.h> // para usar strlen#include <stdlib.h> // para usar exitvoid main( ){ ofstream arq_saida("cadeias_put.txt", ios::out);
if (!arq_saida){ cout<<"arquivo não pode ser aberto:"<<endl;
exit(1);}char str[ ] = "O tempo é um grande professor, pena que
ele acaba matando todos os seus pupilos";for (int i=0; i<strlen(str); i++)
arq_saida.put(str[i]);}
Programação de Computadores 335
#include <fstream.h> // para usar arquivos#include <string.h> // para usar strlen#include <stdlib.h> // para usar exitvoid main( ){ char ch;ifstream arq_entrada("cadeias_put.txt", ios::in);if (!arq_entrada){ cout<<"arquivo não pode ser aberto:"<<endl;
exit(1);}while (arq_entrada){ arq_entrada.get(ch);
cout<<ch;}
}
Programação de Computadores 336
! Uma outra forma de leitura de caracteres de um arquivo "usar a função membro da classe ios chamada rdbuf( )"retorna um ponteiro para o objeto buffer associado ao objeto stream #include <fstream.h>void main( ){ ifstream arq_entrada("cadeias_put.txt", ios::in);
if (!arq_entrada){ cout<<"arquivo não pode ser aberto:"<<endl;
exit(1);}cout<<arq_entrada.rdbuf( );
}
Programação de Computadores 337
! Para armazenar num arquivo grandes quantidades numéricas é mais eficiente usar o modo binário" números são armazenados da forma como são representados na memória ao invés da representação como caracteres.
! inteiro é sempre representado em dois bytes, mas na versão texto 12345 requer 5 bytes; float é sempre representado em 4 bytes, mas na versão texto 6.02314E13 usará 10 bytes.
! Faremos um programa para gravar um arranjo de inteiros no formato binário e depois ler os dados gravados.
! Usaremos duas novas funções: write( ) e read( )" visão dos dados em termos de bytes (tipo char) " transferem um buffer completo de bytes para/do o arquivo em disco. Os parâmetros das duas funções são: o endereço do buffer (tipo char) e seu tamanho.
Programação de Computadores 338
#include <fstream.h>void main( ){ const int MAX =100;
int buffer[MAX];for (int i=0; i<MAX; i++)buffer[i] = i*100; // preenche o arranjo
ofstream saida("dados_binario.dat", ios::out|ios::binary);saida.write((char *)buffer, MAX*sizeof(int)); saida.close( );for (int i=0; i<MAX; i++)buffer[i]=0; //zerando o arranjo para preencher com os dados do arquivo
ifstream entrada("dados_binario.dat", ois::in|ios::binary); //abrindo para ler
entrada.read((char*)buffer, MAX*sizeof(int));for (int i=0; i<MAX;i++)if (buffer[i]!= i*100){ cerr<<"Dados incorretos"; return;}
cout<<"Dados corretos“<<endl;for (int i=0; i<MAX; i++) cout<<' '<<buffer[i];
}
Programação de Computadores 339
! Vamos ver agora como objetos podem ser escritos/ lidos de arquivos
! Vamos usar uma classe chamada pessoa que tem como dados o nome e a idade.class pessoa{ char nome[40];
int idade;public:void entra_dados( )
{ cout<<“Entre com o nome:”; cin>>nome;cout<<“Entre com a idade:”; cin>>idade; }
void mostra_dados( ){ cout<<“Nome=“<<nome<<‘ ‘<<“idade=“<<idade<<endl; }
};
Programação de Computadores 340
// escreve um objeto numa arquivo#include “pessoa.h”#include <fstream/h>void main( ){ pessoa p1;
p1.pega_dados( );ofstream. arq_saida(“pessoas.dat”, ios::out|ios::binary);
arq_saida.write((char*) &p1,sizeof(p1));}
Programação de Computadores 341
// le objeto de um arquivo#include <fstream.h>#include "pessoa.h"void main( ){ pessoa p2;
ifstream arq_entrada("pessoas.dat", ios::in|ios::binary);
arq_entrada.read((char*)&p2, sizeof(p2));p2.mostra_dados( );
}
Programação de Computadores 342
! programa que faz a escrita e leitura de várias pessoas#include <fstream.h>#include "pessoa.h"void main( ){ char ch;
pessoa p1;fstream arquivo;arquivo.open(“pessoas.dat",ios::app|ios::out|ios::in|ios::binary);do{ cout<<"Entre com os dados da pessoa:"<<endl;
p1.entra_dados( );arquivo.write((char*)&p1, sizeof(p1));cout<<"Mais pessoas(S/N):"; cin>>ch;
}while (ch=='s' | ch=='S');arquivo.seekg(0);arquivo.read((char *) &p1, sizeof(p1));cout<<"Pessoas Cadastradas:"<<endl;while (!arquivo.eof( )){ p1.mostra_dados( );arquivo.read((char *) &p1, sizeof(p1));
}}
Programação de Computadores 343
Sobrecarga dos operadores >> e << para arquivos#include <fstream.h>class med_inglesa{ int pes; float polegadas;public:med_inglesa() { pes=0; polegadas=0.0;}med_inglesa (int p, float pol) { pes= p; polegadas = pol;}friend ostream& operator<<(ostream&, const med_inglesa&);friend istream& operator>>(istream&, med_inglesa&);};ostream& operator<<(ostream& saida, const med_inglesa& m){ saida<<m.pes<<"\'-"<<m.polegadas<<'\"'; return saida; }istream& operator>>(istream& entrada, medida_inglesa& m){ char ch; entrada>>m.pes>>ch>>ch>>m.polegadas>>ch;
return entrada; }
Programação de Computadores 344
void main( ){ char resposta;
med_inglesa distancia;ofstream arquivo; arquivo.open("distancias.dat");do{ cout<<"entre com a distancia no formato ingles:";
cin>>distancia; arquivo<<distancia;cout<<"Mais dados (S/N):"; cin>>resposta; }
while (resposta!='N' && resposta!=‘n’);arquivo.close( );ifstream arquivo1; arquivo1.open("distancias.dat");cout<<"Conteudo do arquivo em disco:"<<endl;while (1){ arquivo1>>distancia;if (arquivo1.eof( )) break;cout<<"\ndistancia="<<distancia;
}}
Programação de Computadores 345
Sobrecarga para E/S e, arquivos binários! Vamos utilizar a classe pessoa para desenvolver o
nosso exemplo. A classe pessoa tem um campo para armazenar o nome de tamanho 40 e um campo inteiro para armazenar a idade" arquivo binário"os dados no disco serão representados da mesma maneira que na memória.
! As funções membro da classe pessoa serão usadas para obter os dados a partir da entrada padrão (teclado) e mostrar esses dados na saída padrão.
! Os operadores << e >> serão sobrecarregados para escrever os dados no disco e para ler o arquivo do disco " funções write( ) e read( ) de iostream
Programação de Computadores 346
class pessoa{ char nome[40];
int idade;public:void entra_dados( ){ cout<<"Entre com o nome:"; cin.getline(nome,40);
cout<<"Entre com a idade:"; cin>>idade;cin.ignore(10,’\n’);
}void mostra_dados( ){ cout<<"Nome="<<nome<<" idade="<<idade<<endl;}
void pessoaentra(istream& ) //le arquivo em si mesmovoid pessoasai(ostream&); //escreve dados no arquivofriend istream& operator>>(istream&, pessoa&);friend ostream& operator<<(ostream&, const pessoa&);
};
Programação de Computadores 347
void pessoa::pessoaentra(istream& arq){ arq.read((char*) this, sizeof(*this)); }void pessoa::pessoasai(ostream& arq){ arq.write((char*)this, sizeof(*this)); }istream& operator>>(istream& entra, pessoa& p){ p.pessoaentra(entra); return entra; }ostream& operator<<(ostream& sai, const pessoa& p){ p.pessoasai(sai);
return sai;}
Programação de Computadores 348
! Nesse exemplo, temos alguns pontos a esclarecer.! Os operadores << e >> devem ser funções amigas,
uma vez que uma stream e não um objeto da classe pessoa é usada lado esquerdo.
! Como estamos usando formato binário, é mais conveniente acessarmos objetos pessoa diretamente de sua posição de memória" usando o ponteiro this.
! this não é acessível em funções amigas " usamos outras funções que são membros da classe pessoa (pessoaentra( ) e pessoasai( ))
Programação de Computadores 349
#include <fstream.h>#include "pessoa.h"void main( ){ pessoa p1, p2, p3, p4 ; //criamos 4 pessoascout<<"\nPessoa 1:"; p1.entra_dados( );cout<<"\nPessoa 2:"; p2.entra_dados( );ofstream arq_saida("pessoabin.dat", ios::binary);arq_saida<<p1<<p2;arq_saida.close( );ifstream arq_entrada("pessoabin.dat", ios::binary);arq_entrada>>p3>>p4;cout<<endl<<"Primeira pessoa lida do arquivo:";p3.mostra_dados( );cout<<endl<<"Segunda pessoa lida do arquivo:";p4.mostra_dados( );
}