Sei sulla pagina 1di 6

Universidade Federal de Pelotas

Instituto de Fsica e Matemtica


Departamento de Matemtica, Estatstica e Computao
Bacharelado em Cincia da Computao

Programao I
Prof. Jos Lus Gntzel semestre 2003/1

Aula 9

9 Manipulao de Arquivos em C
(Fonte: SCHILDT, cap 9 p. 219)

A linguagem C no possui nenhum comando de entrada/sada. Todas as operaes de


entrada/sada ocorrem ocorrem mediante chamadas a funes da biblioteca C padro. Embora
tal caracterstica possa, a prrimeira vista, parecer uma desvantagem, na verdade ela permite
que o sistema de arquivos de C seja extremamente poderoso e flexvel. O sistema de
entrada/sada de C nico porque os dados podem ser transferidos na sua representao
binria interna ou em um formato de texto legvel por humanos. Isso torna fcil criar arquivos
que satisfaam qualquer necessidade.

E/S ANSI Versus E/S UNIX.

O padro C ANSI define um conjunto completo de funes de E/S que pode ser utilizado para
ler e escrever quaquer tipo de dado. Por outro lado, o antigo padro C UNIX contm dois
sistemas distintos de rotinas que realizam operaes de E/S. O primeiro mtodo assemelha-se
vagamente ao definido pelo padro C ANSI e denominado sistema de arquivo com buffer
(tambm chamado de formatado ou de alto nvel). O segundo o sistema de arquivo tipo
UNIX (no formatado ou sem buffer) definido apenas sobre o antigo padro UNIX. O padro
ANSI no define o sistema sem buffer porque, entre outras coisas, os dois sistemas so
amplamente redundantes e o sistema de arquivos tipo UNIX pode no ser relevante a certos
ambientes que poderia, de outro modo, suportar C. Nesta disciplina daremos nfase ao
sistema de arquivo C ANSI. O fato de o ANSI no ter definido o sistema de E/S tipo UNIX
sugere que seu uso provavelmente ir declinar. De fato, seria muito dif!cil justificar seu uso
em qualquer projeto atual. Porem, como as rotinas tipo UNIX foram utilizadas em milhares
de programas em C existentes, elas no podem ser ignoradas.

E/S em C Versus E/S em C++.

Como C forma o embasamento de C++ (C melhorada atravs da orientao a objetos), as


vezes surge a pergunta sobre como se relaciona o sistema E/S de C com C++.
C++ suporta todo o sistema de arquivos definido pelo C ANSI. Assim, se voc portar algum
cdigo para C++ em algum momento no futuro, nao precisara modificar todas as rotinas de
E/S. No entanto, C++ tambm define seu prprio sistema de E/S, orientado a objetos, que
inclui tanto funes quanto operadores de E/S. O sistema de E/S C++ duplica por completo a
funcionalidade do sistema de E/S C ANSI. Em geral, se usar C++ para escrever programas
orientados a objetos, voc vai querer usar o sistema de E/S orientado a objetos. Em outros
casos, voc livre para escolher usar o sistema de arquivos orientado a objetos ou o sistema
de arquivos C ANSI. Uma vantagem de usar este ltimo que atualmente ele est
padronizado e ! reconhecido por todos os compiladores C e C++ atuais.
UFPel Bacharelado em Cincia da Computao .- Programao I - semestre 2003/1 prof. J. Gntzel pg. 9-2

Streams e Arquivos

O sistema de E/S de C fornece uma interface consistente ao programador C,


independentemente do dispositivo real que e acessado. Isto , o sistema de E/S de C prov
um nvel de abstrao entre o programador e o dispositivo utilizado. Esta abstrao chamada
de stream e o dispositivo real chamado de arquivo. importante entender como streams e
arquivos se integram.

Streams

O sistema de arquivos de C projetado para trabalhar com uma ampla variedade de


dispositivos, incluindo terminais, acionadores de disco e acionadores de fita. Embora cada um
dos dispositivos seja muito diferente, o sistema de arquivo com buffer transforma-os em um
dispositivo lgico chamado de stream. Todas as streams comportam-se de forma semelhante.
Pelo fato de as streams serem totalmente independentes do dispositivo, a mesma funo pode
escrever em um arquivo em disco ou em algum outro dispositivo, como o console. Existem
dois tipos de streams: texto e binria.

Streams de Texto

Um stream de texto uma seq!ncia de caracteres. O padro C ANSI permite (mas no


exige) que uma stream de texto seja organizada em linhas terminadas por um caractere de
nova linha. Porm, o caractere de nova linha opcional na ltima linha e determinado pela
implementao (a maioria dos compiladores de C no termina streams de texto com caracteres
de nova linha). Em uma stream de texto, certas tradues podem ocorrer conforme exigido
pelo sistema host. Por exemplo, uma nova linha pode ser convertida em um par retorno de
carro/alimentao de linha. Portanto, poder no haver uma relao de um para um entre os
caracteres que so escritos (ou lidos) e aqueles nos dispositivos externos. Alm disso, devido
a possveis tradues, o nmero de caracteres escritos (ou lidos) pode no ser o mesmo que
aquele encontrado no dispositivo externo.

Streams Binrias

Uma stream binria uma seq!ncia de bytes com uma correspondncia de um para um
com aqueles encontrados no dispositivo externo isto , no ocorre nenhuma traduo de
caracteres. Alm disso, o nmero de bytes escritos (ou lidos) o mesmo que o encontrado no
dispositivo externo. Porm, um nmero definido pela implementao de bytes nulos pode ser
acrescentado a um stream binrio. Esse bytes nulos poderiam ser usados para aumentar a
informao para que ela preenchesse um setor de um disco, por exemplo.

Arquivos

Em C, um arquivo pode ser qualquer coisa, desde um arquivo em disco at um terminal ou


uma impressora. Voc associa um stream com um arquivo especfico realizando uma
operao de abertura. Uma vez o arquivo aberto, informaes podem ser trocadas entre ele e o
seu programa.
Nem todos os arquivos apresentam os mesmos recursos. Por exemplo, um arquivo em disco
pode suportar acesso aleatrio (sequencial), enquanto um teclado no pode. Isso releva um
UFPel Bacharelado em Cincia da Computao .- Programao I - semestre 2003/1 prof. J. Gntzel pg. 9-3

ponto importante sobre o sistema de E/S de C: todas as streams so iguais, mas no todos os
arquivos.
Se o arquivo pode suportar acesso aleatrio (algumas vezes referido como solicitao de
posio), abrir este arquivo tambm inicializa o indicador de posi!o no arquivo para o
comeo do arquivo. Quando cada caractere lido ou escrito no arquivo, o indicador de
posio incrementado, garantindo prograssao atravs do arquivo.
Um arquivo e desassociado de uma stream especfica por meio de uma operao de
fechamento. Se um arquivo aberto para sada for fechado, o contedo, se houver algum, da
sua stream associada ser escrito no dispositivo externo. Este processo e geralmente referido
como descarga (flushing) da stream e garante que nenhuma informao seja acidentalmente
deixada no bufffer do disco. Todos os arquivos so fechados automaticamente quando o
programa termina normalemente, com main() retornando ao sistema operacional ou uma
chamada a exit(). Os arquivos no so fechados quando um programa !quebra (crash) ou
quando ele chama abort().
Cada stream associada a um arquivo tem uma estrutura de controle de arquivo do tipo FILE.
Esta estrutura e definida no cabealho stdio.h. Nunca modifique este bloco de controle de
arquivo!
A separao que se faz entre streams e arquivos pode parecer desnecessria ou estranha, mas
sua principal finalidade a consistncia da interface. Em C, voc s precisa pensar em termos
de stream e usar apenas um sistema de arquivos para realizar todas as operaes de entrada e
sada. O compilador C converte a entrada ou sada em linha em uma stream facilmente
gerencivel.

Fundamentos do Sistema de Arquivos

O sistema de arquivos C ANSI composto de diversas funes interrelacionadas. As mais


comuns so mostradas na tabela a seguir. Estas funes exigem que o cabealho stdio.h seja
includo em qualquer programa em que se queira utiliz-las. Note que a maioria das funes
comea com a letra f. Isso uma conveno do padro C UNIX, que definiu dois sistemas
de arquivos. As funes de E/S do UNIX no comeavam com um prefixo e a maioria das
funes do sistema de E/S formatado tinha o prefixo f. O comit de ANSI escolheu manter
esta conveno de nomes para mater esta continuidade.

Nome Funo
fopen() Abre um arquivo
fclose() Fecha um arquivo
puts() Escreve um caractere em um arquivo
fputs() O mesmo de puts()
gets() L um caractere de um arquivo
fgets() O mesmo que gets()
fseek() Posiciona um arquivo em um byte especfico
fprintf() para um arquivo o que printf() para o console
fscanf() para um arquivo o que scan() para o console
feof() Devolve verdadeiro se o fim do arquivo for atingido
ferror() Devolve verdadeiro se ocorreu um erro
rewind() Recoloca o indicador de posio de arquivo no incio do arquivo
remove() Apaga um arquivo
fflush() Descarrega um arquivo
UFPel Bacharelado em Cincia da Computao .- Programao I - semestre 2003/1 prof. J. Gntzel pg. 9-4

O arquivo de cabealho stdio.h fornece os prottipos para as funes de E/S e define estes trs
tipos: size_t, fpos_t e FILE. O tipo size_t essencialemnte o mesmo que um unsigned,
assim como fpos_t. O tipo FILE ser discutido na prxima seo.
stdio.h tambm define vrias macros. As mais relevantes so: NULL, EOF, FOPEN_MAX,
SEEK_SET, SEEK_CUR e SEE_END. A macro NULL define um ponteiro nulo. A macro
EOF geralmente definida como 1 e o valor devolvido quando uma funo de entrada
tenta ler alm do final do arquivo. FOPEN_MAX, define um valor inteiro que determina o
nmero de arquivos que podem estar abertos ao mesmo tempo. As outras macros so usadas
com fseek(), que uma funo que executa acesso aleatrio em um arquivo.

O Ponteiro de Arquivo

O ponteiro o meio comum que une o sistema C ANSI de E/S. Um ponteiro de arquivo um
ponteiro para informaes que definem vrias coisas sobre o arquivo, incluindo seu nome,
status e a posio atual do arquivo. Basicamente, o ponteiro de arquivo identifica um arquivo
especfico em disco e usado pela stream associada para direcionar as operaes das funes
de E/S. Um ponteiro de arquivo uma varivvel ponteiro do tipo FILE. Para ler ou escrever
arquivos, seu programa precisa usar ponteiros de arquivo. Para obter uma varivel ponteiro de
arquivo, use o comando:

FILE *fp;

Abrindo um arquivo

A funo fopen() abre uma stream para uso e associa um arquivo a ela. Ela retorna o ponteiro
de arquivo associado a este arquivo. Mais freqentemente, o arquivo um arquivo em disco.
A funo fopen() tem este prottipo:

FILE fopen(const char* nomearq, const char* modo*);


!
onde nomearq um ponteiro para uma cadeia de caracteres que forma um nome vlido de
arquivo e pode incluir uma especificao de caminho de pesquisa (path). A string apontada
por modo determina como o arquivo ser aberto. A tabela a seguir mostra os valores legais
para modo. strings como r+b tambm podem ser representadas como rb+.
Como exposto, a funo fopen() devolve um ponteiro de arquivo. Seu programa nunca deve
alterar o valor deste ponteiro. Se ocorrer um erro quando estiver tentando abrir um arquivo,
fopen() devolve um ponteiro nulo.
Como mostra a tabela, um arquivo pode ser aberto de modo texto ou binrio. Em muitas
implementaes, no modo texto, seqncias de retorno de carro/alimentao de linha so
traduzidas para caracteres de nova linha na entrada. Na sada, ocorre o inverso: novas linhas
so traduzidas para retornos de carro/alimantaes de linha. Nenhuma traduo deste tipo
ocorre em arquivos binrios.

Modo Significado
r Abre um arquivo-texto para leitura
w Cria um arquivo-texto para escrita
a Anexa a um arquivo-texto
rb Abre um arquivo binrio para leitura
wb Cria um arquivo binrio para escrita
ab Anexa um arquivo binrio
UFPel Bacharelado em Cincia da Computao .- Programao I - semestre 2003/1 prof. J. Gntzel pg. 9-5

r+ Abre um arquivo-texto para leitura/escrita


w+ Cria um arquivo-texto para leitura/escrita
a+ Anexa ou cria um arquivo-texto para leitura/escrita
r+b Abre um arquivo binrio para leitura/escrita
w+b Cria um arquivo binrio para leitura/escrita
a+b Anexa um arquivo binrio para leitura/escrita

Para abrir um arquivo chamado arquivo1, permitindo escrita, pode-se digitar:

FILE *fp;
fp = fopen( arquivo1, w);

Uma maneira mais profissional de escrever o trecho anterior e:

FILE *fp;
If((fp = fopen( arquivo1, w)) == NULL )
{
printf(nao foi possivel abrir o arquivo\n);
exit(1);
}

Neste segundo caso, qualquer erro na abertura do arquivo ser detectado (e.g., disco cheio ou
protegido contra gravao).
Em geral, voc sempre deve confirmar o sucesso de fopen() antes de tentar qualquer outra
operao sobre o arquivo!

Se voc usar fopen() para abrir um arquivo compermisso para escrita, qualquer arquiv j
existente com esse nome ser apagado e um novo arquivo ser iniciado. Se nenhum arquivo
com este nome existe, um ser criado. Se voc deseja adicionar ao final do arquivo, deve usar
o modo a. Arquivos j existentes s podem ser abertos para operaes de leitura. Se o
arquivo no existe, um erro devolvido. Finalemente, se um arquivo aberto para operaes
de leitura/escrita, ele no ser apagado caso j exista e, seno existir, ele ser criado.
O nmero que de arquivos que pode ser aberto em um determinado momento especificado
por FOPEN_MAX. Este nmero geralmente superior a 8, mas voc deve verificar no
manual do seu compilador qual o seu valor exato.

Fechando um Arquivo

A funo fclose() fecha uma stream que foi aberta por meio de uma chamada a fopen(). Ela
escreve qualquer dade que ainda permanece no buffer de disco no arquivo e, ento, fecha
normalmente o arquivo em nvel de sistema operacional. Uma falha ao fechar uma stream
atrai todo o tipo de problema, incluindo perda de dados, arquivos destrudos e possveis erros
intermitentes em seu programa. Uma fclose() tambm libera o bloco de controle de arquivo
associado stream, deixando-o disponvel para reutilizao. Em muitos casos, h um limite
do sistema operacional para o nmero de arquivos abertos simultaneamente, assim, voc deve
fechar um arquivo antes de abrir outro.
A funo fclose() tem o seguinte prottipo:

int fclose(FILE *fp);

onde fp o ponteiro de arquivo devolvido pela chamada a fopen(). Um valor de retorno zero
significa uma operao de fechamento bem sucedida. Qualquer outro valor indica um erro. A
UFPel Bacharelado em Cincia da Computao .- Programao I - semestre 2003/1 prof. J. Gntzel pg. 9-6

funo padro ferror() pode ser utilizada para determinar e informar qualquer problema.
Geralmente, fclose() falhar quando um disco tiver sido retirado prematuramente do
acionador ou no houver mais espa!o no disco.

Escrevendo um Caractere

O padro C ANSI define duas funes equivalentes para escrever caracteres: puts() e fputs().
(Tecnicamente, puts() implementada como macro.) H duas funes idnticas simplesmente
para preservar a compatibilidade com verses mais antigas de C.
A funo puts() escreve caracteres em um arquivo que foi previamente aberto para escrita por
meio de fopen(). O prottipo para esta funo :

int puts(int ch, FILE *fp);

onde fp um ponteiro de arquivo devolvido por fopen() e ch o caractere a ser escrito. O


ponteiro de arquivo informa a puts() em que arquivo em disco escrever. Por razes histricas,
ch definido como um int, mas apenas o byte menos significativo utilizado.
Se a operao puts() for bem sucedida, ela devolver o caractere escrito. Caso contrrio,
devolve EOF.

Lendo um Caractere

O padro ANSI define duas funes para ler um caractere getc() e fgetc() para preservar a
compatibilidade com verses anteriores de C.
A funo getc() l caracteres de um arquivo aberto no modo leitura por fopen(). O prottipo
de getc() :

int getc(FILE *fp);

onde fp um ponteiro de arquivo devolvido do tipo FILE devolvido por fopen().Por razes
histricas, getc() devolve um inteiro, mas o byte mais significativo zero.
A funo getc() devolve EOF quando o final do arquivo for alcanado. O cdigo seguinte
poderia ser utilizado para ler um arquivo texto at que a marca de final de arquivo seja lida.

do
{
ch = getc(fp);
} while(ch != EOF);

No entanto, getc() tambm retorna EOF quando ocorre um erro. Voc pode usar ferror() para
determinar precisamente o que ocorreu.

Potrebbero piacerti anche