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