Título:Fechando Arquivos Automaticamente
Linguagem:C/C++
S.O.:DOS/Windows
Autor(es):Wenderson Teixeira
Muitas vezes, quando estamos fazendo um programa, nós evitamos colocar tratamentos de erro, para manter o código limpo e não ter que ficar alterando o algorítimo para fechar os arquivos abertos, imprimir mensagens de erro na abertura dos mesmo e coisas deste tipo, no entanto certificar-se que o arquivo que foi aberto seja fechado, é essencial para evitar transtornos futuros, como por exemplo, execer o número máximo de arquivos que podem ser abertos simultaneamente.
Neste artigo vamos ver como fechar automaticamente os arquivos em C e em C++.
Em primeiro lugar, a biblioteca padrão do C (não é ANSI), nos fornece uma função chamada fcloseall
que fecha todos os arquivos abertos de uma única vez, mas só isso não resolve o nosso problema completamente, pois ainda assim teríamos que chamar a função cada vez que detectassemos um erro e quisessemos sair do programa, para esta segunda tarefa temos atexit
que registra uma função de saída, e quando o seu programa é terminado, essa função é chamada automaticamente, você pode registrar até 32 funções de saída, o código ficaria então assim:
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <process.h> // Função que será registrada por atexit void cleanup(void { // Fecha todos os arquivos abertos fcloseall(); // Imprime mensagem e espera uma tecla para demostrar que a função foi chamada puts("Clean Up Method"); getch(); } int main(void) { int c; // Registrar a função cleanup, que será chamada quando o programa terminar atexit(cleanup); // Abre o mesmo arquivo diversas vezes e não se preocupa em fechá-lo for(c = 0; c < 150; c++) if(!fopen("cleanup.obj", "rb")) { // Se houver erro, imprime uma mensagem e retorna 1 para o processo chamador puts("Erro ao abrir cleanup.obj"); return 1; } // Sai, retornando 0, para indicar que não houve erros return 0; }
Já em C++, pode-se, além desse método, utilizar outro ainda mais eficiciente. Criando-se uma classe simples e que não faz nada além de abrir, testar e fechar o arquivo, pode-se obter um efeito muito interessante, pois como se sabe, um objeto ou variável local, só é válido dentro do escopo onde foi declarado, ou seja, no bloco mais interno ao qual ele pertença. Ex.:
{ { int c = 0; TObj obj; // c e obj são válidos somente aqui } // Aqui não se possui mais nenhuma referência a c ou obj }
Isto é válido para laços for
, while
e todo tipo de bloco de código iniciado por '{' e terminado por '}'.
A classe ficaria então assim:
#include <stdio.h> #include <stdlib.h> #include <conio.h> // Classe que fecha automaticamente o arquivo quando o objeto é apagado class TAutoCloseFile { private: FILE *fp; public: TAutoCloseFile(const char *szFilename, const char *szMode = "r") { // abre o arquivo e verifica erro fp = fopen(szFilename, szMode); if(fp == NULL) ErrorMessage(szFilename); } ~TAutoCloseFile() { // se o arquivo foi aberto, deve ser fechado if(fp) fclose(fp); } virtual void ErrorMessage(const char *szFilename) { // imprime mensagem de erro e termina o programa. // esta função pode ser modificada ou mesmo instanciada // para funcionar em plataformas diferentes do DOS printf("Erro ao abrir %s\n", szFilename); exit(1); } operator FILE *() { // operador que retorna um FILE *, para uso com as funções normais de arquivo return fp; } }; int main() { char *str = new char[256]; // Mostra a utilização de forma dinâmica TAutoCloseFile *config = new TAutoCloseFile("c:\\config.sys"); printf("-------------------------[ Config.sys ]-------------------------\n"); while(!feof((FILE *)*config)) { if(fgets(str, sizeof(char) * 256, *config)) printf(str); } // Não se esquece sempre de deletar o objeto delete config; printf("---------------------[ Fim do Config.sys ]----------------------\n\n"); // Mostra a utilização de forma estática, onde o objeto não precisa ser apagado TAutoCloseFile autoexec("c:\\autoexec.bat"); printf("------------------------[ Autoexec.bat ]------------------------\n"); while(!feof((FILE *)autoexec)) { if(fgets(str, sizeof(char) * 256, autoexec)) printf(str); } printf("--------------------[ Fim do Autoexec.bat ]---------------------\n\n"); delete str; return 0; }