Arquivos na Linguagem C

Praticamente todas as aplicações necessitam
armazenar ou ler dados de arquivos de dados
A linguagem C oferece 2 formas básicas de
manipulação com arquivos
» E/S de alto nível
– Bufferização interna
– Uso de STREAMS
– Utiliza apontadores para arquivos: FILE *

» E/S de baixo nível
– Utiliza chamadas semelhantes às System Calls do UNIX
– Bufferização externa, fornecida pelo programador
– Manipula diretamente os descritores de arquivos do Sistema
Operacional

Arquivos na Linguagem C

STREAMS
» Streams são fluxos de dados armazenados em buffers de
memória interna e associados a arquivos em dispositivos
externos
» Na linguagem C um stream está associado a um tipo de
dado denominado FILE * e pode ser denominado de
apontador de arquivos
» A E/S de alto nível utiliza streams
» A conexão de um arquivo a um stream é feita abrindo o
arquivo. A conexão termina quando o mesmo é fechado.

O tratamento de arquivos de alto-nível em C faz uso
do tipo de dados FILE que está definido em stdio.h

E/S de Alto Nível

No Turbo C a definição de FILE é a seguinte:
typedef struct {
int level;
/* fill/empty level of buffer */
unsigned flags;
/* File status flags */
char fd;
/* File descriptor */
unsigned char hold; /* Ungetc char */
int bsize;
/* Buffer size */
unsigned char *buffer;/* Data buffer */
unsigned char *curp; /* Current pointer */
unsigned istemp;
/* Temporary file */
short token;
/* Validity checking */
} FILE;

 Quando um programa inicia sua execução 3 streams são abertos automaticamente » stdin (associado à entrada padrão) » stdout (associado à saída padrão) » stderr (associado à saída padrão de erros) . » As principais funções são: fopen( ). getc( ). fflush( ). fclose( ).E/S de Alto Nível » O programador não precisa conhecer nem se preocupar com o conteúdo do tipo FILE. fputs( ). fprintf( ). » Precisa apenas utilizá-lo nas chamadas às funções de manipulação de arquivos de alto nível. fscanf( ). ferror( ). putc( ). fgets( ). fseek( ).

ou NULL se houver um erro #include <stdio.fopen() » fopen() abre o arquivo indicado e retorna um stream.abre um arquivo texto para leitura. mas não podem ser alterados  Abertura de arquivos .E/S de Alto Nível » Os nomes destes streams estão associados a constantes simbólicas e podem ser usados em quaisquer operações onde se use apontadores de arquivos. . const char *modo) "r" . elimina o conteúdo anterior se houver.h> FILE *fopen(const char *nome. "w" .cria um arquivo texto para gravação.

o conteúdo anterior é mantido inalterado. e as conversões \n para CR+LF não serão realizadas . "w+" .abre arquivo de texto para atualização. "r+b") significa que o arquivo é tratado como binário.E/S de Alto Nível "a" .abre ou cria um arquivo de texto para gravação no final do arquivo "r+" . » É fundamental testar o retorno de fopen( ) para garantir que o arquivo foi aberto com sucesso.abre ou cria um arquivo de texto para atualização no final do arquivo.cria arquivo de texto para atualização. "a+" . elimina o conteúdo anterior se houver. » Se o modo incluir um b em seu final ("wb".

if ((fp = fopen("teste".h> main() { FILE *fp. } /* Faz uso do arquivo */ } . "w")) == NULL) { perror("teste"). return (1).E/S de Alto Nível  Exemplo com fopen() #include <stdio.

libera qualquer área de memória alocada dinamicamente para o stream e fecha o arquivo associado. mas é importante fechar arquivos que não estejam mais sendo utilizados.h> int fclose(FILE *stream).fclose() » fclose() grava no disco qualquer dado pendente no buffer interno. » Em C todos os arquivos abertos são fechados quando a aplicação termina de forma normal. pois há um limite para o número de arquivos abertos por aplicação.E/S de Alto Nível  Fechando arquivos . . #include <stdio. Retorna EOF se houve um erro e zero caso contrário.

return (1). "w")) == NULL) { perror("teste"). if ((fp = fopen("teste".E/S de Alto Nível  Exemplo com fclose() #include <stdio. } /* Faz uso do arquivo */ fclose(fp). } .h> main() { FILE *fp.

Retornam o caracter escrito com sucesso ou EOF em caso de falha. Devolvem EOF em caso de erro. .E/S de Alto Nível  Lendo caracteres .getc() e fgetc() » getc() e fgetc() são funcionalmente equivalentes e lêem o próximo caracter do stream passado como parâmetro.putc() e fputc() » putc() e fputc() são funcionalmente equivalentes e escrevem um caracter no stream passado como parâmetro. #include <stdio. int fgetc(FILE *stream).  Escrevendo caracteres .h> int getc(FILE *stream). A diferença é que putc() pode ser uma macro. A diferença é que getc() pode ser uma macro.

» As rotinas getchar() e putchar() vistas anteriormente são implementadas com base em getc() e putc(). FILE *stream). stdout) . int fputc(int c. respectivamente: #define getchar() getc(stdin) #define putchar(c) putc((c).E/S de Alto Nível #include <stdio. uma vez que estas são bufferizadas.h> int putc(int c. o que as torna mais rápidas. » Vale observar que embora estas funções recebam caracter a caracter. as operações com o disco não são realizadas desta forma. FILE *stream).

Exemplo: Utilitário cat do UNIX #include <stdio. Copia stdin */ copia_arq(stdin.h> void copia_arq(FILE *fp_in. if (argc == 1) { /* Nenhum argumento. } else { while (--argc > 0) if ((fp = fopen(*++argv. } else { . "r")) == NULL) { perror(*argv). main(int argc. stdout). return (1). char *argv[]) { FILE *fp. FILE *fp_out).

} } return (0). FILE *fp_out) { int c. } } . fp_out). } void copia_arq(FILE *fp_in. fclose(fp). stdout). while ((c = getc(fp_in)) != EOF) { putc(c.Exemplo: Utilitário cat do UNIX copia_arq(fp.

EOF não pode ser devolvido. #include <stdio. Retorna EOF em caso de falha ou um valor não negativo em caso de sucesso.h> int ungetc(int c.  Escrevendo e Lendo Cadeias » fputs() escreve uma cadeia no arquivo e a segue por um new-line (\n). .ungetc() » ungetc() devolve um caracter de volta no stream. FILE *stream).E/S de Alto Nível  Devolvendo caracteres . Só é garantida a devolução de um único caractere. » ungetc() retorna o caracter devolvido em caso de sucesso e EOF em caso de falha.

h> int fputs(const char *s.E/S de Alto Nível #include <stdio. Retorna a cadeia lida em caso de sucesso ou NULL em caso de erro. #include <stdio. . » fgets() lê uma cadeia de caracteres de um stream. int n.h> char *fgets(char *s. Recebe um parâmetro que especifica o tamanho máximo da cadeia a ser lida. A leitura pára se for encontrado um \n. FILE *stream). FILE *stream).

..)  fscanf(stdin. const char *formato.. printf(.).E/S de Alto Nível  Entrada/Saída formatada » fscanf() é semelhante a scanf(). só que recebe um parâmetro a mais indicando o stream onde devem ser escritos os dados.. #include <stdio. .h> int fprintf(FILE *fp.h> int fscanf(FILE *fp.... #include <stdio. scanf(.)..)  fprintf(stdout.. const char *formato. .. . ..) » fprintf() é semelhante a printf()..) . só que recebe um parâmetro a mais indicando o stream de onde devem ser lidos os dados.

. FILE *stream). #include <stdio. size_t quantidade. Retorna o número de objetos realmente lidos. size_t tamanho. Os objetos a serem armazenados devem estar em um vetor de dados.h> size_t fread(void *buf. » fwrite() escreve num stream um conjunto de objetos de um tamanho especificado. armazenando-os em um vetor de dados. fwrite() retorna o número de objetos realmente escritos.E/S de Alto Nível  Leitura/Escrita Direta » fread() lê de um stream um conjunto de objetos de um tamanho especificado.

. » fflush() retorna zero no caso de sucesso e EOF em caso de falha. size_t tamanho.  Descarregando o conteúdo do buffer » fflush() sobre um stream de saída. size_t quantidade.E/S de Alto Nível #include <stdio. grava no arquivo associado quaisquer dados armazenados no buffer e ainda não escritos em disco. FILE *stream).h> size_t fwrite(const void *buf.h> int fflush(FILE *fp). #include <stdio.

final do arquivo . int origem). » a posição é estabelecida pelo deslocamento de desloc bytes a partir de origem.E/S de Alto Nível  Manipulando a posição de arquivo » fseek() estabelece a posição atual do arquivo (em bytes) para o stream indicado. Retorna zero em caso de sucesso e um valor diferente de zero em caso de erro. #include <stdio. long desloc.posição atual do arquivo – SEEK_END . que pode assumir os seguintes valores: – SEEK_SET .Início do arquivo – SEEK_CUR .h> int fseek(FILE *fp.

h> void rewind(FILE *stream). . #include <stdio. #include <stdio.h> long ftell(FILE *stream).E/S de Alto Nível » rewind() desloca a posição atual de arquivo para o início do mesmo. rewind(fp)  fseek(fp. 0L. SEEK_SET) » ftell() retorna a posição atual do arquivo associado ao stream. ou -1L em caso de erro.

h> contém o código do último erro ocorrido. #include <stdio.h> int ferror(FILE *stream). » Variável errno definida em <errno.E/S de Alto Nível  Manipulando erros » ferror() retorna um valor diferente de zero se o indicador de erro para o stream indicado estiver setado.h> int feof(FILE *stream). » feof() retorna um valor diferente de zero se o indicador fim de arquivo para o stream indicado estiver setado. . #include <stdio.

#include <stdio. » perror() imprime na saída padrão de erros a string passada como parâmetro seguida de dois pontos (:) e uma mensagem associada a o último erro ocorrido. s. "%s: %s\n". sys_errlist[errno]) . perror(s)  fprintf(stderr.h> void perror(const char *s).E/S de Alto Nível  Manipulando erros » clearerr() apaga os indicadores de erro e fim de arquivo para o stream especificado.h> void clearerr(FILE *stream). #include <stdio.

#include <stdio. #include <stdio.E/S de Alto Nível  Outras operações com arquivos » remove() elimina do disco o arquivo cujo nome é passado como parâmetro. Retorna valor não zero em caso de falha. Retorna zero em caso de sucesso e um valor não zero em caso de falha. const char *nome_novo).h> int remove(const char *nomearq).h> int rename(const char *nome_ant. . » rename() modifica o nome de um arquivo.

Recebe um apontador para o vetor que irá armazenar o nome ou NULL. » tmpnam() devolve um nome de arquivo temporário não existente no diretório corrente.E/S de Alto Nível  Arquivos temporários » tmpfile() cria um arquivo temporário no modo "w+b". #include <stdio. .h> char *tmpnam(char *strnome). caso em que é devolvido o endereço de um vetor estático interno.h> FILE *tmpfile(void). #include <stdio. Retorna um stream válido em caso de sucesso e NULL em caso de falha. este arquivo será removido automaticamente quando for fechado.

» São devolvidos pelas rotinas de E/S de baixo nível que abrem ou criam um arquivo » São utilizados como um parâmetro em todas as rotinas de E/S de baixo nível que fazem a manipulação com o arquivos » Toda aplicação em C já recebe três arquivos abertos. que têm os seguintes descritores: – 0 (associado à entrada padrão) – 1 (associado à saída padrão) – 2 (associado à saída padrão de erros) .E/S de Baixo Nível  Descritores de Arquivos » Descritores de arquivos são números inteiros que identificam um arquivo junto ao sistema operacional.

octal c/ permissões de acesso ao arquivo .cria arquivo perms . int perms) nome .h> int open(char *nome. ou -1 se houver um erro #include <fcntl.nome do arquivo (incluindo path) a abrir. modo . int modo.indica como o arquivo deve ser aberto: O_RDONLY .leitura/escrita O_CREAT .só leitura O_WRONLY .E/S de Baixo Nível  Abertura de arquivos: open() » open() abre o arquivo indicado e retorna um descritor de arquivo válido.só escrita O_RDWR .

0644).h> int creat(char *nome. Se o arquivo não existir o mesmo será criado com as permissões rw-r--r- Criação de arquivos: creat() » creat() cria o arquivo indicado contendo as permissões de acesso estabelecidas. Abre arquivo para realizar leitura/escrita.E/S de Baixo Nível int fd. ou -1 se houver um erro #include <io.nome do arquivo (incluindo path) a criar perms . O_RDWR | O_CREAT. fd = open("teste".octal c/ permissões de acesso ao arquivo no formato rwxrwxrwx . int perms) nome . Retorna um descritor de arquivo válido.

E/S de Baixo Nível int fd. Cria arquivo com as permissões rwxr-xr-x  Fechando arquivos: close() » close() fecha um arquivo anteriormente aberto com open() ou creat(). 0755). . #include <io. fd = creat("teste".h> int close(int fd). Devolve -1 em caso de erro.

Em caso de sucesso devolve o total de bytes realmente lidos. #include <io. void *buf. #include <io.h> int read(int fd.h> int write(int fd. Em caso de sucesso devolve o total de bytes escritos. unsigned tam). unsigned tam). .  Lendo Dados: read() » read() lê até n bytes do arquivo indicado pelo descritor de arquivo escrevendo os dados lidos no buffer especificado. e -1 em caso de erro.E/S de Baixo Nível  Escrevendo Dados: write() » write() escreve n bytes no arquivo indicado pelo descritor de arquivo a partir do buffer especificado. void *buf. e -1 em caso de erro.

fprintf(stderr. fd2. fprintf(stderr. n.\n").cp com rotinas de baixo nível #include <io. } . "\tcp <arq1> <arq2>\n").h> main(int argc. char buf[BUFSIZ]. char *argv[]) { int fd1.h> #include <stdio. if (argc != 3) { fprintf(stderr. exit(1). "Argumentos invalidos.h> #include <fcntl. "Formato correto:\n").

0666)) == -1) { perror(*argv). n) != n) { fprintf(stderr. exit(3). O_RDONLY. close(fd2). 0)) == -1 || (fd2 = creat(*++argv. exit(2). } } close(fd1). } while ((n = read(fd1. buf. return (0). sizeof(buf)) > 0) { if (write(fd2.cp com rotinas de baixo nível if ((fd1 = open(*++argv. } ."cp: erro ao gravar %s\n". *argv). buf.

são os mesmos usados em fseek: – SEEK_SET .final do arquivo .h> long lseek(int fd.E/S de Baixo Nível  Alterando a posição de arquivos: lseek() » lseek() força a posição atual de um arquivo para um valor resultante da união do desloca-mento em bytes e a origem. Retorna o deslocamento da nova posição atual em relação ao inicio do arquivo e o valor -1 em caso de erro. int origem). #include <io. » os valores de origem. long desloc.posição atual do arquivo – SEEK_END .Início do arquivo – SEEK_CUR .

h> int unlink(char *nomearq). .  Eliminando arquivos: unlink() » unlink() elimina o arquivo cujo nome foi passado como parâmetro.E/S de Baixo Nível  Obtendo a posição atual: tell() » tell() devolve a posição atual do arquivo. #include <io. como um deslocamento em bytes em relação ao início do arquivo. No sucesso devolve 0 e em caso de erro -1.h> long tell(int fd). Em caso de erro devolve -1. #include <io.