Segue tutorial muito útil para a manipulação de arquivos em C.
Manipulação de Arquivos em C
(Fonte: SCHILDT, cap 9 p. 219)
A linguagem C não possui nenhum comando de entrada/saída. Todas as operações de
entrada/saída ocorrem ocorrem mediante chamadas a funções da biblioteca C padrão. Embora
tal característica possa, a prrimeira vista, parecer uma desvantagem, na verdade ela permite
que o sistema de arquivos de C seja extremamente poderoso e flexível. O sistema de
entrada/saída de C é único porque os dados pçodem ser transferidos na sua representação
binária interna ou em um formato de texto legível por humanos. Isso torna fácil criar arquivos
que satisfaçam qualquer necessidade.
E/S ANSI Versus E/S UNIX.
O padrão C ANSI define um conjunto completo de funções de E/S que pode ser utilizado para
ler e escrever quaquer tipo de dado. Por outro lado, o antigo padrão C UNIX contém dois
sistemas distintos de rotinas que realizam operações de E/S. O primeiro método assemelha-se
vagamente ao definido pelo padrão C ANSI e é denominado sistema de arquivo com buffer
(também chamado de formatado ou de alto nível). O segundo é o sistema de arquivo tipo
UNIX (não formatado ou sem buffer) definido apenas sobre o antigo padrão UNIX. O padrão
ANSI não define o sistema sem buffer porque, entre outras coisas, os dois sistemas são
amplamente redundantes e o sistema de arquivos tipo UNIX pode não 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 não 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. Poreém, como as rotinas tipo UNIX foram utilizadas em milhares
de programas em C existentes, elas não podem ser ignoradas.
E/S em C Versus E/S em C++.
Como C forma o embasamento de C++ (C melhorada através da orientação 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
código para C++ em algum momento no futuro, naão precisara modificar todas as rotinas de
E/S. No entanto, C++ também define seu próprio sistema de E/S, orientado a objetos, que
inclui tanto funções 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.
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 nível de abstração entre o programador e o dispositivo utilizado. Esta abstração é 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 lógico chamado de stream. Todas as streams comportam-se de forma semelhante.
Pelo fato de as streams serem totalmente independentes do dispositivo, a mesma função pode
escrever em um arquivo em disco ou em algum outro dispositivo, como o console. Existem
dois tipos de streams: texto e binária.
Streams de Texto
Um stream de texto é uma seq!üência de caracteres. O padrão C ANSI permite (mas não
exige) que uma stream de texto seja organizada em linhas terminadas por um caractere de
nova linha. Porém, o caractere de nova linha é opcional na última linha e é determinado pela
implementação (a maioria dos compiladores de C não termina streams de texto com caracteres
de nova linha). Em uma stream de texto, certas traduções podem ocorrer conforme exigido
pelo sistema host. Por exemplo, uma nova linha pode ser convertida em um par retorno de
carro/alimentação de linha. Portanto, poderá não haver uma relação de um para um entre os
caracteres que são escritos (ou lidos) e aqueles nos dispositivos externos. Além disso, devido
a possíveis traduções, o número de caracteres escritos (ou lidos) pode não ser o mesmo que
aquele encontrado no dispositivo externo.
Streams Binárias
Uma stream binária é uma seq!üência de bytes com uma correspondência de um para um
com aqueles encontrados no dispositivo externo – isto é, não ocorre nenhuma tradução de
caracteres. Além disso, o número de bytes escritos (ou lidos) é o mesmo que o encontrado no
dispositivo externo. Porém, um número definido pela implementação de bytes nulos pode ser
acrescentado a um stream binário. Esse bytes nulos poderiam ser usados para aumentar a
informação 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 específico realizando uma
operação de abertura. Uma vez o arquivo aberto, informações 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 aleatório (sequencial), enquanto um teclado não pode. Isso releva um
ponto importante sobre o sistema de E/S de C: todas as streams são iguais, mas não todos os
arquivos.
Se o arquivo pode suportar acesso aleatório (algumas vezes referido como solicitação de
posição), abrir este arquivo também inicializa o indicador de posi!ção no arquivo para o
começo do arquivo. Quando cada caractere é lido ou escrito no arquivo, o indicador de
posição é incrementado, garantindo prograssao através do arquivo.
Um arquivo eé desassociado de uma stream específica por meio de uma operação de
fechamento. Se um arquivo aberto para saída for fechado, o conteúdo, 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 informação seja acidentalmente
deixada no bufffer do disco. Todos os arquivos são fechados automaticamente quando o
programa termina normalemente, com main() retornando ao sistema operacional ou uma
chamada a exit(). Os arquivos não são 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 cabeçalho stdio.h. Nunca modifique este bloco de controle de
arquivo!
A separação que se faz entre streams e arquivos pode parecer desnecessária ou estranha, mas
sua principal finalidade é a consistência da interface. Em C, você só precisa pensar em termos
de stream e usar apenas um sistema de arquivos para realizar todas as operações de entrada e
saída. O compilador C converte a entrada ou saída em linha em uma stream facilmente
gerenciável.
Fundamentos do Sistema de Arquivos
O sistema de arquivos C ANSI é composto de diversas funções interrelacionadas. As mais
comuns são mostradas na tabela a seguir. Estas funções exigem que o cabeçalho stdio.h seja
incluído em qualquer programa em que se queira utilizá-las. Note que a maioria das funções
começa com a letra “f”. Isso é uma convenção do padrão C UNIX, que definiu dois sistemas
de arquivos. As funções de E/S do UNIX não começavam com um prefixo e a maioria das
funções do sistema de E/S formatado tinha o prefixo “f”. O comitê de ANSI escolheu manter
esta convenção de nomes para mater esta continuidade.
Nome Função
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 específico
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 posição de arquivo no início do arquivo
remove() Apaga um arquivo
fflush() Descarrega um arquivo
O arquivo de cabeçalho stdio.h fornece os protótipos para as funções de E/S e define estes três
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 próxima seção.
stdio.h também define várias macros. As mais relevantes são: 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 função de entrada
tenta ler além do final do arquivo. FOPEN_MAX, define um valor inteiro que determina o
número de arquivos que podem estar abertos ao mesmo tempo. As outras macros são usadas
com fseek(), que é uma função que executa acesso aleatório 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 informações que definem várias coisas sobre o arquivo, incluindo seu nome,
status e a posição atual do arquivo. Basicamente, o ponteiro de arquivo identifica um arquivo
específico em disco e é usado pela stream associada para direcionar as operações das funções
de E/S. Um ponteiro de arquivo é uma variávvel ponteiro do tipo FILE. Para ler ou escrever
arquivos, seu programa precisa usar ponteiros de arquivo. Para obter uma variável ponteiro de
arquivo, use o comando:
FILE *fp;
Abrindo um arquivo
A função fopen() abre uma stream para uso e associa um arquivo a ela. Ela retorna o ponteiro
de arquivo associado a este arquivo. Mais freqüentemente, o arquivo é um arquivo em disco.
A função fopen() tem este protótipo:
FILE fopen(const char* nomearq, const char* modo*);
!
onde nomearq é um ponteiro para uma cadeia de caracteres que forma um nome válido de
arquivo e pode incluir uma especificação 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” também podem ser representadas como “rb+”.
Como exposto, a função 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 binário. Em muitas
implementações, no modo texto, seqüências de retorno de carro/alimentação de linha são
traduzidas para caracteres de nova linha na entrada. Na saída, ocorre o inverso: novas linhas
são traduzidas para retornos de carro/alimantações de linha. Nenhuma tradução deste tipo
ocorre em arquivos binários.
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 binário para leitura
wb Cria um arquivo binário para escrita
ab Anexa um arquivo binário
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 binário para leitura/escrita
w+b Cria um arquivo binário para leitura/escrita
a+b Anexa um arquivo binário 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 gravação).
Em geral, você sempre deve confirmar o sucesso de fopen() antes de tentar qualquer outra
operação sobre o arquivo!
Se você usar fopen() para abrir um arquivo compermissão 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 operações de leitura. Se o
arquivo não existe, um erro é devolvido. Finalemente, se um arquivo é aberto para operações
de leitura/escrita, ele não será apagado caso já exista e, senão existir, ele será criado.
O número que de arquivos que pode ser aberto em um determinado momento é especificado
por FOPEN_MAX. Este número geralmente é superior a 8, mas você deve verificar no
manual do seu compilador qual é o seu valor exato.
Fechando um Arquivo
A função 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, então, fecha
normalmente o arquivo em nível de sistema operacional. Uma falha ao fechar uma stream
atrai todo o tipo de problema, incluindo perda de dados, arquivos destruídos e possíveis erros
intermitentes em seu programa. Uma fclose() também libera o bloco de controle de arquivo
associado à stream, deixando-o disponível para reutilização. Em muitos casos, há um limite
do sistema operacional para o número de arquivos abertos simultaneamente, assim, você deve
fechar um arquivo antes de abrir outro.
A função fclose() tem o seguinte protótipo:
int fclose(FILE *fp);
onde fp é o ponteiro de arquivo devolvido pela chamada a fopen(). Um valor de retorno zero
significa uma operação de fechamento bem sucedida. Qualquer outro valor indica um erro. A
função padrão ferror() pode ser utilizada para determinar e informar qualquer problema.
Geralmente, fclose() falhará quando um disco tiver sido retirado prematuramente do
acionador ou não houver mais espa!ço no disco.
Escrevendo um Caractere
O padrão C ANSI define duas funções equivalentes para escrever caracteres: puts() e fputs().
(Tecnicamente, puts() é implementada como macro.) Há duas funções idênticas simplesmente
para preservar a compatibilidade com versões mais antigas de C.
A função puts() escreve caracteres em um arquivo que foi previamente aberto para escrita por
meio de fopen(). O protótipo para esta função é:
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 razões históricas,
ch é definido como um int, mas apenas o byte menos significativo é utilizado.
Se a operação puts() for bem sucedida, ela devolverá o caractere escrito. Caso contrário,
devolve EOF.
Lendo um Caractere
O padrão ANSI define duas funções para ler um caractere – getc() e fgetc() – para preservar a
compatibilidade com versões anteriores de C.
A função getc() lê caracteres de um arquivo aberto no modo leitura por fopen(). O protótipo
de getc() é:
int getc(FILE *fp);
onde fp é um ponteiro de arquivo devolvido do tipo FILE devolvido por fopen().Por razões
históricas, getc() devolve um inteiro, mas o byte mais significativo é zero.
A função getc() devolve EOF quando o final do arquivo for alcançado. O código 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() também retorna EOF quando ocorre um erro. Você pode usar ferror() para
determinar precisamente o que ocorreu.
Manipulação de Arquivos em C
(Fonte: SCHILDT, cap 9 p. 219)
A linguagem C não possui nenhum comando de entrada/saída. Todas as operações de
entrada/saída ocorrem ocorrem mediante chamadas a funções da biblioteca C padrão. Embora
tal característica possa, a prrimeira vista, parecer uma desvantagem, na verdade ela permite
que o sistema de arquivos de C seja extremamente poderoso e flexível. O sistema de
entrada/saída de C é único porque os dados pçodem ser transferidos na sua representação
binária interna ou em um formato de texto legível por humanos. Isso torna fácil criar arquivos
que satisfaçam qualquer necessidade.
E/S ANSI Versus E/S UNIX.
O padrão C ANSI define um conjunto completo de funções de E/S que pode ser utilizado para
ler e escrever quaquer tipo de dado. Por outro lado, o antigo padrão C UNIX contém dois
sistemas distintos de rotinas que realizam operações de E/S. O primeiro método assemelha-se
vagamente ao definido pelo padrão C ANSI e é denominado sistema de arquivo com buffer
(também chamado de formatado ou de alto nível). O segundo é o sistema de arquivo tipo
UNIX (não formatado ou sem buffer) definido apenas sobre o antigo padrão UNIX. O padrão
ANSI não define o sistema sem buffer porque, entre outras coisas, os dois sistemas são
amplamente redundantes e o sistema de arquivos tipo UNIX pode não 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 não 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. Poreém, como as rotinas tipo UNIX foram utilizadas em milhares
de programas em C existentes, elas não podem ser ignoradas.
E/S em C Versus E/S em C++.
Como C forma o embasamento de C++ (C melhorada através da orientação 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
código para C++ em algum momento no futuro, naão precisara modificar todas as rotinas de
E/S. No entanto, C++ também define seu próprio sistema de E/S, orientado a objetos, que
inclui tanto funções 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.
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 nível de abstração entre o programador e o dispositivo utilizado. Esta abstração é 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 lógico chamado de stream. Todas as streams comportam-se de forma semelhante.
Pelo fato de as streams serem totalmente independentes do dispositivo, a mesma função pode
escrever em um arquivo em disco ou em algum outro dispositivo, como o console. Existem
dois tipos de streams: texto e binária.
Streams de Texto
Um stream de texto é uma seq!üência de caracteres. O padrão C ANSI permite (mas não
exige) que uma stream de texto seja organizada em linhas terminadas por um caractere de
nova linha. Porém, o caractere de nova linha é opcional na última linha e é determinado pela
implementação (a maioria dos compiladores de C não termina streams de texto com caracteres
de nova linha). Em uma stream de texto, certas traduções podem ocorrer conforme exigido
pelo sistema host. Por exemplo, uma nova linha pode ser convertida em um par retorno de
carro/alimentação de linha. Portanto, poderá não haver uma relação de um para um entre os
caracteres que são escritos (ou lidos) e aqueles nos dispositivos externos. Além disso, devido
a possíveis traduções, o número de caracteres escritos (ou lidos) pode não ser o mesmo que
aquele encontrado no dispositivo externo.
Streams Binárias
Uma stream binária é uma seq!üência de bytes com uma correspondência de um para um
com aqueles encontrados no dispositivo externo – isto é, não ocorre nenhuma tradução de
caracteres. Além disso, o número de bytes escritos (ou lidos) é o mesmo que o encontrado no
dispositivo externo. Porém, um número definido pela implementação de bytes nulos pode ser
acrescentado a um stream binário. Esse bytes nulos poderiam ser usados para aumentar a
informação 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 específico realizando uma
operação de abertura. Uma vez o arquivo aberto, informações 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 aleatório (sequencial), enquanto um teclado não pode. Isso releva um
ponto importante sobre o sistema de E/S de C: todas as streams são iguais, mas não todos os
arquivos.
Se o arquivo pode suportar acesso aleatório (algumas vezes referido como solicitação de
posição), abrir este arquivo também inicializa o indicador de posi!ção no arquivo para o
começo do arquivo. Quando cada caractere é lido ou escrito no arquivo, o indicador de
posição é incrementado, garantindo prograssao através do arquivo.
Um arquivo eé desassociado de uma stream específica por meio de uma operação de
fechamento. Se um arquivo aberto para saída for fechado, o conteúdo, 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 informação seja acidentalmente
deixada no bufffer do disco. Todos os arquivos são fechados automaticamente quando o
programa termina normalemente, com main() retornando ao sistema operacional ou uma
chamada a exit(). Os arquivos não são 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 cabeçalho stdio.h. Nunca modifique este bloco de controle de
arquivo!
A separação que se faz entre streams e arquivos pode parecer desnecessária ou estranha, mas
sua principal finalidade é a consistência da interface. Em C, você só precisa pensar em termos
de stream e usar apenas um sistema de arquivos para realizar todas as operações de entrada e
saída. O compilador C converte a entrada ou saída em linha em uma stream facilmente
gerenciável.
Fundamentos do Sistema de Arquivos
O sistema de arquivos C ANSI é composto de diversas funções interrelacionadas. As mais
comuns são mostradas na tabela a seguir. Estas funções exigem que o cabeçalho stdio.h seja
incluído em qualquer programa em que se queira utilizá-las. Note que a maioria das funções
começa com a letra “f”. Isso é uma convenção do padrão C UNIX, que definiu dois sistemas
de arquivos. As funções de E/S do UNIX não começavam com um prefixo e a maioria das
funções do sistema de E/S formatado tinha o prefixo “f”. O comitê de ANSI escolheu manter
esta convenção de nomes para mater esta continuidade.
Nome Função
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 específico
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 posição de arquivo no início do arquivo
remove() Apaga um arquivo
fflush() Descarrega um arquivo
O arquivo de cabeçalho stdio.h fornece os protótipos para as funções de E/S e define estes três
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 próxima seção.
stdio.h também define várias macros. As mais relevantes são: 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 função de entrada
tenta ler além do final do arquivo. FOPEN_MAX, define um valor inteiro que determina o
número de arquivos que podem estar abertos ao mesmo tempo. As outras macros são usadas
com fseek(), que é uma função que executa acesso aleatório 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 informações que definem várias coisas sobre o arquivo, incluindo seu nome,
status e a posição atual do arquivo. Basicamente, o ponteiro de arquivo identifica um arquivo
específico em disco e é usado pela stream associada para direcionar as operações das funções
de E/S. Um ponteiro de arquivo é uma variávvel ponteiro do tipo FILE. Para ler ou escrever
arquivos, seu programa precisa usar ponteiros de arquivo. Para obter uma variável ponteiro de
arquivo, use o comando:
FILE *fp;
Abrindo um arquivo
A função fopen() abre uma stream para uso e associa um arquivo a ela. Ela retorna o ponteiro
de arquivo associado a este arquivo. Mais freqüentemente, o arquivo é um arquivo em disco.
A função fopen() tem este protótipo:
FILE fopen(const char* nomearq, const char* modo*);
!
onde nomearq é um ponteiro para uma cadeia de caracteres que forma um nome válido de
arquivo e pode incluir uma especificação 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” também podem ser representadas como “rb+”.
Como exposto, a função 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 binário. Em muitas
implementações, no modo texto, seqüências de retorno de carro/alimentação de linha são
traduzidas para caracteres de nova linha na entrada. Na saída, ocorre o inverso: novas linhas
são traduzidas para retornos de carro/alimantações de linha. Nenhuma tradução deste tipo
ocorre em arquivos binários.
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 binário para leitura
wb Cria um arquivo binário para escrita
ab Anexa um arquivo binário
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 binário para leitura/escrita
w+b Cria um arquivo binário para leitura/escrita
a+b Anexa um arquivo binário 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 gravação).
Em geral, você sempre deve confirmar o sucesso de fopen() antes de tentar qualquer outra
operação sobre o arquivo!
Se você usar fopen() para abrir um arquivo compermissão 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 operações de leitura. Se o
arquivo não existe, um erro é devolvido. Finalemente, se um arquivo é aberto para operações
de leitura/escrita, ele não será apagado caso já exista e, senão existir, ele será criado.
O número que de arquivos que pode ser aberto em um determinado momento é especificado
por FOPEN_MAX. Este número geralmente é superior a 8, mas você deve verificar no
manual do seu compilador qual é o seu valor exato.
Fechando um Arquivo
A função 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, então, fecha
normalmente o arquivo em nível de sistema operacional. Uma falha ao fechar uma stream
atrai todo o tipo de problema, incluindo perda de dados, arquivos destruídos e possíveis erros
intermitentes em seu programa. Uma fclose() também libera o bloco de controle de arquivo
associado à stream, deixando-o disponível para reutilização. Em muitos casos, há um limite
do sistema operacional para o número de arquivos abertos simultaneamente, assim, você deve
fechar um arquivo antes de abrir outro.
A função fclose() tem o seguinte protótipo:
int fclose(FILE *fp);
onde fp é o ponteiro de arquivo devolvido pela chamada a fopen(). Um valor de retorno zero
significa uma operação de fechamento bem sucedida. Qualquer outro valor indica um erro. A
função padrão ferror() pode ser utilizada para determinar e informar qualquer problema.
Geralmente, fclose() falhará quando um disco tiver sido retirado prematuramente do
acionador ou não houver mais espa!ço no disco.
Escrevendo um Caractere
O padrão C ANSI define duas funções equivalentes para escrever caracteres: puts() e fputs().
(Tecnicamente, puts() é implementada como macro.) Há duas funções idênticas simplesmente
para preservar a compatibilidade com versões mais antigas de C.
A função puts() escreve caracteres em um arquivo que foi previamente aberto para escrita por
meio de fopen(). O protótipo para esta função é:
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 razões históricas,
ch é definido como um int, mas apenas o byte menos significativo é utilizado.
Se a operação puts() for bem sucedida, ela devolverá o caractere escrito. Caso contrário,
devolve EOF.
Lendo um Caractere
O padrão ANSI define duas funções para ler um caractere – getc() e fgetc() – para preservar a
compatibilidade com versões anteriores de C.
A função getc() lê caracteres de um arquivo aberto no modo leitura por fopen(). O protótipo
de getc() é:
int getc(FILE *fp);
onde fp é um ponteiro de arquivo devolvido do tipo FILE devolvido por fopen().Por razões
históricas, getc() devolve um inteiro, mas o byte mais significativo é zero.
A função getc() devolve EOF quando o final do arquivo for alcançado. O código 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() também retorna EOF quando ocorre um erro. Você pode usar ferror() para
determinar precisamente o que ocorreu.
Comment