Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto...

27
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 ... 9 8 7 6 5 4 3 2 1 marca de fim de arquivo

Transcript of Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto...

Page 1: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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

Page 2: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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.

Page 3: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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

Page 4: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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;}

Page 5: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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

Page 6: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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.

Page 7: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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;

}

Page 8: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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.

Page 9: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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

Page 10: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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

Page 11: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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;}

}

Page 12: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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]);}

Page 13: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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;}

}

Page 14: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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( );

}

Page 15: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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.

Page 16: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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];

}

Page 17: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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; }

};

Page 18: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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));}

Page 19: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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( );

}

Page 20: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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));

}}

Page 21: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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; }

Page 22: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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;

}}

Page 23: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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

Page 24: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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&);

};

Page 25: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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;}

Page 26: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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( ))

Page 27: Processamento de Arquivos€¦ · ! ofstream arq_saida("fdados.txt“, ios::out);" cria um objeto da classe ofstream chamado arq_saida associado com o arquivo fdados.txt aberto para

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( );

}