Skip to content

Tratamento de arquivos em C. Parte 1

Este mini tiny micro tutorial :) sobre tratamento de arquivos tenta mostrar de
forma prática como você pode abrir/escrever/apagar arquivos na linguagem C.

Neste tutorial utilizarei o arquivo de checksum dos CDs do Debian, disponível
em [1]. Os códigos estão em Aqui, Aqui, Aqui e Aqui

Teoria sobre arquivos.

Os passos necessários para abrir um arquivo são:
0) declare a biblioteca <stdio.h>
1) declarar um ponteiro XPTO do tipo FILE (basicamente).
2) informar o endereço/caminho do arquivo a ser aberto.
3) realizar as operações necessárias leitura/escrita.
4) fechar o arquivo associado ao ponteiro XPTO.

Quando um arquivo é aberto o ponteiro XPTO é referência, isto é, este ponteiro
“sabe” a localização do arquivo no disco e os parâmetros utilizados para sua
abertura como, por exemplo, se o arquivo será aberto apenas como leitura ou
leitura/escrita.

Abrindo o arquivo.

Para abrir um arquivo são necessários duas funções presentes na stdio.h,
‘fopen’ e ‘fclose’. A primeira abre o arquivo e a última fecha. A sintaxe de
abertura é muito simples e possui dois argumentos, o caminho onde o arquivo
está localizado e o modo de abertura. Vamos supor que você esteja usando
Linux e o seu arquivo esteja na pasta ‘Documents’ ou ‘Documentos’ do seu
usuário. O caminho seria /home/ubuntu/Documents/MD5SUMS, caso esteja usando
Windows (sei lá onde fica) c:\MD5SUMS ?

XPTO = fopen(caminho_do_arquivo, modo_de_abertura)

O modo de leitura é como você deseja abrir o arquivo. Por exemplo, não existe
necessidade de modificação no conteúdo do arquivo, você deve abrir no modo
‘somente leitura’:

XPTO = fopen("/home/ubuntu/Documents/MD5SUMS", "r");

Caso você queira abrir apenas para gravação, use o modo ‘somente gravação’:

XPTO = fopen("/home/ubuntu/Documents/MD5SUMS", "w");

É importante observar os modos de abertura de arquivo:

r – permite apenas leitura do arquivo. O arquivo deve existir, caso contrário
a operação retorna erro.
w – permite apenas gravação no arquivo. Não é possível ler do arquivo.Se o
arquivo aberto com modo “w” já existir, uma arquivo vazio será criado.
r+ – Abre um arquivo existe para leitura e gravação
w+ – Cria um arquivo novo para leitura e gravação.
a+ – Modo append, cria um arquivo novo ou abre um arquivo existente para
leitura e gravação.

Além desses parâmetros existem outras opções para leitura. Veja a documentação
em [2].

O código abaixo é a estrutura básica para abertura de um arquivo. O arquivo
MD5SUMS está no próprio diretório desse código em C. Na linha ‘5’ o ponteiro
do tipo FILE é definido, ‘p_arquivo’. A linha ‘8’ representa a rotina de
abertura do arquivo no modo apenas leitura. O arquivo é fechado na linha ’11’.

1    #include <stdio.h>
2
3    int main()
4    {
5        FILE* p_arquivo = NULL;
6
7        //abre o arquivo
8        p_arquivo = fopen(“MD5SUMS”, “r”);
9
10        //fecha o arquivo
11        fclose(p_arquivo);
12        return 0;
13    }

Dicas: Toda vez que você tentar abrir um arquivo é necessário validar se o
mesmo foi aberto corretamente, isto é, você deve checar se o ponteiro é
diferente de nulo (NULL).

#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* p_arquivo = NULL;
//abre o arquivo
p_arquivo = fopen(“MD5SUMS”, “r”);
if (p_arquivo == NULL)
{
printf(“Erro na abertura do arquivo\n”);
exit(1); //sai se tiver error
}

//fecha o arquivo
fclose(p_arquivo);
return 0;
}

Leitura do arquivo

Estando com o arquivo aberto podemos fazer a leitura do mesmo. Porém, antes
de avançar nesse tópico é importante entender algumas definições sobre
arquivo:

EOF – End of file ou ‘fim do arquivo’ é uma macro utilizada para indiciar que
a leitura do arquivo chegou ao seu fim, ou seja, não há mais nada a ser lido
do arquivo [3, 4]. Esta macro retorna um valor inteiro que pode ser avaliado.
O EOF também pode ser utilizado para sinalizar um erro aleatório. Por isso,
segundo o manual da libc [5], a função ‘feof’ é mais sugerida que EOF. Veremos os
dois exemplos.

A leitura do conteúdo pode ser a partir da função ‘fgetc’ que lê um caractere
por vez do arquivo.

Usando o EOF.

A linha 'while ( (letra = fgetc(p_arquivo)) != EOF )' pode ser traduzida em
algo do tipo: enquanto o retorno da função ‘fgetc’ não for igual a EOF, faça
alguma coisa.

#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE* p_arquivo = NULL;
char letra;

//abre o arquivo
p_arquivo = fopen(“MD5SUMS”, “r”);

if (p_arquivo == NULL)
{
printf(“Erro na abertura do arquivo\n”);
exit(1);
}

while ( (letra = fgetc(p_arquivo)) != EOF ) {
printf(“%c”, letra);
}

//fecha o arquivo
fclose(p_arquivo);
return 0;
}

Usando o feof

Alguns desenvolvedores não gostam de usar o ‘feof’ devido o mesmo retornar
verdadeiro se a última função falhar [6,7,8]. Em termos práticos, o exemplo
seguinte imprime a última linha duas vezes ou imprime lixo de memória:

#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE* p_arquivo = NULL;
char letra;

//abre o arquivo
p_arquivo = fopen(“MD5SUMS”, “r”);

if (p_arquivo == NULL)
{
printf(“Erro na abertura do arquivo\n”);
exit(1);
}

while ( feof(p_arquivo) == 0 ) {
letra = fgetc(p_arquivo);
printf(“%c”, letra);
}

//fecha o arquivo
fclose(p_arquivo);
return 0;
}

Isso acontece porque após a última linha ser lida, a função ‘feof’ ainda
retornará falso e o laço (loop) continuará, portanto quando a função ‘fgetc’
for executada, ela pode retornar o valor anterior ou algum lixo de memória.
Esse comportamento pode ser contornado fazendo um ‘break’ caso o sinal de EOF
tenha sido marcado.

#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE* p_arquivo = NULL;
char letra;

//abre o arquivo
p_arquivo = fopen(“MD5SUMS”, “r”);

if (p_arquivo == NULL)
{
printf(“Erro na abertura do arquivo\n”);
exit(1);
}

while(1){
letra = fgetc(p_arquivo);
if (feof(p_arquivo))
break;
printf(“%c”, letra);
}

//fecha o arquivo
fclose(p_arquivo);
return 0;
}

Outra abordagem pode ser usando a função ‘feof’ duas vezes

#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE* p_arquivo = NULL;
char letra;

//abre o arquivo
p_arquivo = fopen(“MD5SUMS”, “r”);

if (p_arquivo == NULL)
{
printf(“Erro na abertura do arquivo\n”);
exit(1);
}

while ( feof(p_arquivo) == 0 ) {
letra = fgetc(p_arquivo);
if (feof(p_arquivo))
break;

printf(“%c”, letra);
}

//fecha o arquivo
fclose(p_arquivo);
return 0;
}

Se você tiver outra solução, por favor faça comentários.

Exercício:
1) Implemente um código em C que conte a quantidade de linhas e caracteres no
arquivo.
2) Implemente um código em C que conte a quantidade total de caracteres individuais
no arquivo. Por exemplo, se o arquivo tiver apenas uma linha de conteúdo ‘aabbcd’, seu programa deverá imprimir
a – 2
b – 2
c – 1
d – 1

Importante:

a) Depois que o “ponteiro” foi desassociado do arquivo  através da função
‘fclose’, qualquer operação posterior falhará.
b) Segundo o manual da libc [5] é melhor usar a função ‘feof’ que EOF.
c) Faça a dupla validação caso você use a função ‘feof’.
d) Pratique!

Até a próxima.

1 – http://cdimage.debian.org/debian-cd/6.0.6/amd64/iso-cd/MD5SUMS
2 – http://www.gnu.org/software/libc/manual/html_node/Opening-Streams.html
3 – http://pt.wikipedia.org/wiki/EOF
4 – http://www.cplusplus.com/reference/clibrary/cstdio/EOF/
5 – http://www.gnu.org/software/libc/manual/html_node/EOF-and-Errors.html
6 – http://www.drpaulcarter.com/cs/common-c-errors.php
7 – http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1046476070
8 – http://msdn.microsoft.com/en-us/library/aa272678%28v=vs.60%29.aspx

 

Comments are closed.