Anda di halaman 1dari 11

Renato Cardoso Mesquita Departamento de Eng. Eltrica da UFMG renato@cpdee.ufmg.

br

Programao Orientada a Objetos em C++

5 -a . Manipulao de arquivos em C++


. . . . .

5-a. 1. Introduo entrada e sada em arquivos em C++

Os servios de entrada e sada em C++ so implementados atravs da biblioteca iostream, uma biblioteca que implementa uma hierarquia de classes orientadas a objeto, que fazem uso de heranas simples e mltiplas. Para utilizar os servios desta biblioteca, necessrio usar : #include <iostream> As operaes de entrada e sada padro so implementadas, respectivamente, pelas classes istream e ostream. Os objetos cin, cout e cerr pertencem a estas classes. Tambm existe a classe iostream, derivada simultaneamente de istream e ostream, que implementa operaes de entrada e sada em um mesmo objeto. Para a entrada e sada de arquivos, existem as classes: ifstream, derivada de istream, que conecta um arquivo a um programa, para entrada; ofstream, derivada de ostream, que conecta um arquivo a um programa, para sada;

Outros mecanismos da linguagem C++ - Arquivos Pg. 2 fstream, derivada de iostream, que conecta um arquivo a um programa, para entrada e sada. Para poder utilizar a entrada e sada via arquivo, necessrio usar: #include <fstream> Os operadores de fluxo de entrada >> e de sada << so suportados nos objetos destas classes e podem ser sobrecarregados para efetuar a entrada e sada de classes criadas pelo usurio. Para abrir um arquivo apenas para sada, definimos um objeto da classe ofstream: ofstream outFile ("copy.out", ios_base::out); ofstream outFile2("teste.out"); Os argumentos passados para o construtor especificam o nome do arquivo a ser aberto e o modo de abertura a ser usado. Um arquivo de sada pode ser aberto no modo de sada, ios_base::out, ou append, ios_ base::app. Por default, o arquivo aberto no modo de sada. Alguns compiladores mais antigos no conhecem a classe ios_base. Se isto acontecer com seu compilador, substitua ios_base por ios. Se um arquivo j existente for aberto no modo sada, todo seu contedo eliminado. Se quisermos preserv-lo, devemos abri-lo no modo append. Antes de tentar escrever ou ler em um arquivo, sempre uma boa idia verificar se ele foi aberto sem problemas. Pode-se test-lo usando: if(!outFile ) { // Abertura falhou ... cerr << " copy.out no pode ser aberto para sada\n"; exit(-1); } Como a classe ofstream derivada de ostream, todas as operaes existentes em ostream (e portanto existentes em cout) podem ser

Outros mecanismos da linguagem C++ - Arquivos Pg. 3 aplicados em um objeto de ofstream, inclusive as operaes de fluxo de sada sobrecarregadas: char ch = ' '; string teste = "ABCTeste"; outFile.put( '1' ).put( ')' ).put( ch ); outFile << "1 + 1 = " << (1 + 1) << endl; outFile << teste << endl; Para abrir um arquivo apenas para entrada, um objeto da classe ifstream utilizado. O programa abaixo l um arquivo especificado pelo usurio e o copia para a sada padro e outro arquivo, tambm especificado pelo usurio: #include <fstream> #include <string> // da STL ... using namespace std; int main() { cout << "Nome do arquivo de entrada: "; string nome_arquivo_entrada; cin >> nome_arquivo_entrada; ifstream inFile (nome_arquivo_entrada.c_str( ) ); if(!inFile ) { cerr << "No foi possivel abrir o arquivo de entrada : " << nome_arquivo_entrada << " Saindo do programa! \n"; return -1; } cout << "\nNome do arquivo de sada: "; string nome_arquivo_saida; cin >> nome_arquivo_saida; ofstream outFile (nome_arquivo_saida.c_str( ) ); if(!outFile ) { cerr << "No foi possivel abrir o arquivo de saida : " << nome_arquivo_saida << " Saindo do programa! \n"; return -1; } char ch; while (inFile.get(ch) ) {

Outros mecanismos da linguagem C++ - Arquivos Pg. 4 cout.put (ch); outFile.put(ch); } } Objetos das classes ofstream e ifstream podem ser declarados sem estarem associados a um arquivo. Um arquivo pode ser conectado posteriormente, chamando a funo membro open( ); Um arquivo pode ser desconectado de um programa, chamando a funo membro close( ); #include <fstream> using namespace std; const int fileCnt = 5; string fileTable [ fileCnt ] = { "JorgeAmado.txt", "GuimaraesRosa.txt", "CarlosDrummond.txt", "RubemBraga.txt", "ClariceLispector.txt" }; int main() { ifstream inFile; // no est associado a nenhum arquivo for (int ix = 0; ix < fileCnt; ix++) { inFile.open (fileTable[ix].c_str() ); // ... Verifica se a abertura teve sucesso // ... Processa o arquivo inFile.close( ); } } Um objeto da classe fstream pode abrir um arquivo tanto para sada quanto para entrada. A classe fstream derivada da classe iostream.

#include <fstream> int main () { fstream file; int i, j, k; file.open( "teste.txt", ios_base::in); file >> i; // ...

// abertura para leitura // leitura usando file

Outros mecanismos da linguagem C++ - Arquivos Pg. 5 file.close(); // ... file.open("teste.txt", ios_base::app); file << endl << j << k <<endl; file.close(); } Um objeto da classe fstream pode ser aberto para leitura e escrita simultneas: fstream io ("teste.txt", ios_base::in | ios_base::app ); O arquivo pode ser reposicionado usando as funes membro seekg() ou seekp(). (o g indica posicionamento para buscar caracteres (g de get) e o p indica posicionamento para armazenar caracteres (p de put)). As funes podem ser usadas para fazer a movimentao para uma "posio absoluta" ou para se deslocar de um "offset" em relao a uma determinada posio. seekg(pos_type posicao); // Vai para uma posio absoluta. 0 a posio de incio do arquivo: especificado em bytes seekg(off_type offset, ios_base::seekdir dir); // offset em relao a alguma posio, em alguma direo dir pode ser: ios_base::beg, incio do arquivo; ios_base::cur, posio corrente do arquivo; ios_base::end, final do arquivo; Lembre-se que se seu compilador for antigo, voc deve substituir ios_base por ios . Supondo a leitura de registros com tamanho sizeof(Registro), poderamos posicionar o arquivo para leitura de cada um dos i registros atravs de: for (int i = 0; i < registroCont ; i++) readFile.seekg(i*sizeof(Registro), ios_base::beg); Avano de um registro em relao posio corrente: readFile.seekg(sizeof(Registro), ios_base::cur); Pode-se especificar um deslocamento negativo:

Outros mecanismos da linguagem C++ - Arquivos Pg. 6

readFile.seekg(-10, ios_base::cur); Pode-se obter a posio corrente de um arquivo com as funes membro tellg() e tellp() (novamente, g = get e p = put). Por exemplo: ios_base:: pos_type mark = writeFile.tellp(); // guarda posio // ... if(cancelEntry) writeFile.seekp (mark); // retorna posio armazenada Para compiladores mais antigos, substituir ios_base::pos_type por streampos. Exemplo: o programa abaixo l um arquivo texto. Devemos calcular o tamanho em bytes do arquivo e armazenar este valor no final do arquivo. Alm disto, cada vez que se encontrar um caracter de nova linha, devemos armazenar o tamanho em bytes do incio do arquivo at aquela linha (incluindo o caracter de nova linha), no final do arquivo. Por exemplo, dado o arquivo: abcd efg hi j O resultado ser: abcd efg hi j 5 9 12 14 24 #include <iostream> #include <fstream> using namespace std; int main() { fstream inOut ("copy.out" , ios_base::in | ios_base :: app); int cnt = 0; // Contador de bytes char ch;

Outros mecanismos da linguagem C++ - Arquivos Pg. 7

inOut.seekg(0); /* como foi aberto no modo append, ele estaria posicionado no final do arquivo necessrio posicionar no incio ! */ while (inOut.get (ch) ) { cout.put( ch ); // Ecoa na saida cnt++; if ( ch == '\n' ) { // Armazena a posio corrente ios_base::pos_type mark = inOut.tellg(); inOut << cnt << ' '; inOut.seekg (mark ); // Restaura a posio } } // Ao final do loop acima, inOut encontrou o fim de arquivo. // Portanto no est em estado que permita escrever o // tamanho total. O estado deve ser restaurado com a funo // membro clear() inOut.clear (); inOut << cnt << endl; cout << "\nTotal de caracteres: " << cnt << "\n" ; return 0; } 5- 2. Estados do fluxo No exemplo final da seo anterior, usamos a funo clear() para restaurar o estado do arquivo, que se encontrava (eof) e no podia mais ser escrito. As bibliotecas de entrada e sada do C++ nos permitem verificar o estado de cada fluxo de entrada e sada e desta forma sabermos se ele est ou no em um estado de erro. Por exemplo, se escrevermos: int ival; cin >> ival;

Outros mecanismos da linguagem C++ - Arquivos Pg. 8 e teclarmos "Jorge Amado" como entrada, cin colocado em estado de erro. Uma operao de leitura somente ser efetuada por um fluxo de entrada que esteja em estado OK. Para testar se um fluxo est em estado de erro, fazemos: if (!cin) .... Um objeto de fluxo mantm um conjunto de flags de condio atravs dos quais o estado do fluxo pode ser monitorado. Funes especficas so usadas para verificar os estados: eof() retorna verdadeiro se o fluxo encontrou o final do arquivo; bad() retorna verdadeiro se houve uma tentativa de efetuar uma operao invlida, como, por exemplo, efetuar um seek em uma posio posterior ao final do arquivo; fail() retorna verdadeiro se uma operao no obteve sucesso, como, por exemplo, falha na tentativa de abertura de arquivo ou erro no formato dos dados de entrada; good() retorna verdadeiro se nenhuma das trs condies anteriores for verdadeira. Existem dois mtodos para modificar explicitamente o estado de um objeto iostream. A funo clear() reseta o estado. A funo setstate() adiciona determinada condio para o estado. Os valores que podem ser utilizados em setstate so: ios_base::badbit ios_base::eofbit ios_base::failbit ios_base::goodbit Para setar mltiplos estados, pode-se combin-los atravs da operao ou bit a bit: is.setstate( ios_base::badbit | ios_base::failbit); A funo clear pode tambm ser usada para limpar explicitamente um determinado estado: cin.clear(ios_base::goodbit); A funo rdstate() permite acessar explicitamente o estado do objeto para recuperao posterior: ios_base::iostate old_state = cin.rdstate(); cin.clear(); process_input(); // Agora reseta cin para o valor antigo cin.clear ( old_state);

Outros mecanismos da linguagem C++ - Arquivos Pg. 9 5-a. 3. Fluxos em strings A biblioteca iostream permite operaes em memria sobre objetos string. Para utiliza-las necessrio incluir: #include <sstream> A funo abaixo l um arquivo texto em um objeto da classe string, retornando o objeto. Supe-se que o arquivo j esteja aberto.

#include <string> #include <fstream> #include <sstream> string read_file_into_string(ifstream ifile) { ostringstream buf; char ch; while (buf && ifile.get (ch ) ) buf.put ( ch ); /* O buffer cresce na medida do necessrio para acomodar os caracteres de entrada */ return buf.str(); } int main( ) { cout << " Nome do arquivo a ser lido: "; string nome_arquivo; cin >> nome_arquivo; ifstream arquivo(nome_arquivo.c_str()); if(!arquivo) { cout << " No consigo abrir o arquivo: " << nome_arquivo; exit (-1); } string texto = read_file_into_string(arquivo); cout << texto; return 0; }

Outros mecanismos da linguagem C++ - Arquivos Pg. 10 Pode-se escrever normalmente para um fluxo string, usando os operadores de fluxo tradicionais e os sobrecarregados: ostringstream saida; saida << "Valor de i: " << i << " Valor de j: " << j << endl; string msg = saida.str( ); cout << "Tamanho da string de mensagem: " << msg.size() << " Mensagem: " << msg << endl; Um istringstream l a partir de um objeto string com o qual foi construido. Um uso de istring na transformao de uma string em valores aritmticos. Exemplo: string valores = "10 40 50 7.54"; istringstream str_entrada ( valores ); int i, j, k; float x; stringstream_entrada >> i >> j >> k >> x ; 5.a. 4. Formatao.

Cada classe das bibliotecas iostream mantm um "estado de formatao" que controla os detalhes das operaes de formatao. Este estado pode ser alterado atravs de manipuladores ou de sinalizadores de formato (uso das funes membro setf() e unsetf()), como estudado no primeiro captulo deste curso. O conjunto completo de manipuladores, definido pela norma ANSI C++ apresentado na tabela abaixo. As opes em negrito so os valores default. No se esquecer de: #include <iomanip>

Manipulador boolalpha noboolalpha showbase noshowbase showpoint noshowpoint showpos

Significado representa variveis booleanas atravs de true e false representa variveis booleanas atravs de 0 e 1 gera um prefixo indicando a base numrica no gera um prefixo indicando a base numrica sempre gera um ponto decimal somente mostra um ponto decimal com fraes mostra o sinal + em nmeros no negativos

Outros mecanismos da linguagem C++ - Arquivos Pg. 11 noshowpos skipws no mostra o sinal + em nmeros no negativos ignora os espaos em branco nos operadores de entrada noskipws no ignora os espaos em branco nos operadores de entrada uppercase imprime 0X em hexadecimal e E em notao cientfica nouppercase imprime 0x em hexadecimal e e em notao cientfica dec imprime em base 10 hex imprime em base hexadecimal oct imprime em base octal left adiciona caracteres de preenchimento a direita do valor right adiciona caracteres de preenchimento a esquerda do valor internal adiciona caracteres de preenchimento entre o sinal e o valor fixed imprime pontos flutuantes em notao decimal scientific imprime pontos flutuantes em notao cientfica flush limpa o buffer de sada ends insere um null e ento limpa o buffer de sada endl insere um newline e ento limpa o buffer de sada ws "come" os espaos em branco setfill (ch) caracteres em branco sero preenchidos com ch setprecision(n) preciso em ponto flutuante setada em "n" setw(n) le ou escreve o valor em w caracteres setbase(b) faz a sada de inteiros na base b int i=10, j=20, k = 30;

cout << "i em decimal = " << i << " i em hexadecimal " << hex << i << flush;

Anda mungkin juga menyukai