Aula 16: Manipulação de Arquivos em C Fernanda Passos Universidade Federal Fluminense Programação de Computadores IV Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 1 / 33
Agenda 1 Revisão e Contexto 2 Entrada e Saída 3 Manipulação de Arquivos em C Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 2 / 33
Agenda 1 Revisão e Contexto 2 Entrada e Saída 3 Manipulação de Arquivos em C Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 3 / 33
Aula Anterior: Vetores e Matrizes: declaração, acesso a elementos, estrutura em memória. String: É vetor de caracteres com terminado nulo. Declaração, inicialização e acesso aos elementos. A manipulação pode ser feita como um vetor ou através de funções da biblioteca string.h. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 4 / 33
Foco da Aula de Hoje Arquivos: Fundamentos de arquivos. Manipulação em ANSI C: abrir e fechar, escrever e ler de um arquivo texto, identificar fim de arquivo. Objetivos: Aprender a manipular arquivos através de um programa em C. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 5 / 33
Agenda 1 Revisão e Contexto 2 Entrada e Saída 3 Manipulação de Arquivos em C Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 6 / 33
Entrada e Saída em C Comandos de Entrada e Saída (E/S ou I/O) são aqueles responsáveis por se comunicar com o mundo externo. E/S padrões são o teclado e tela, respectivamente. Mas existem outros: mouse, impressora, placa de rede, sistema de arquivos. Em C, os comandos de E/S são fornecidos através de funções disponíveis no stdio.h. Todas essas funções são capazes de manipular streams. Streams são fluxos de dados associados a um arquivo. Arquivo representa algum dispositivo de E/S. Pode ser um arquivo em disco, um terminal, uma impressora... Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 7 / 33
Stream e Arquivos Existem dois tipos de stream (ou fluxo de dados): Stream de Texto: o fluxo é representado por uma sequência de caracteres. Stream Binário: o fluxo é composto por uma sequência de bytes lidos, sem tradução, diretamente do dispositivo externo. Por exemplo, a E/S padrão usa stream de texto. Um arquivo é associado a um stream através de uma operação de abertura. E desassociado através de uma operação de fechamento. Uma vez o arquivo aberto, podemos manipulá-lo através de algum tipo de stream. Em nosso curso, veremos apenas arquivo em disco com stream de texto. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 8 / 33
Agenda 1 Revisão e Contexto 2 Entrada e Saída 3 Manipulação de Arquivos em C Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 9 / 33
Funções Comuns para Manipulação de Arquivos Função fopen() fclose() fprintf() fscanf() putc(), fputc() getc(), fgetc() fseek() rewind() feof() ferror() fflush() remove() fread() fwrite() Descrição Abre um arquivo. Fecha um arquivo. Equivalente a printf(), usando stream. Equivalente a scanf(), usando stream. Escreve um caractere em um arquivo. Lê um caractere de um arquivo. Posiciona o arquivo em um ponto específico. Posiciona o arquivo no início. Retorna verdadeiro se chegou ao fim do arquivo. Retorna verdadeiro na ocorrência de erro. Descarrega o buffer associado com o arquivo. Apaga um arquivo. Leitura de dados no modo binário. Escrita de dados no modo binário. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 10 / 33
Declaração de um Arquivo Um arquivo é declarado através de um protótipo de tipo chamado FILE. Será um ponteiro do tipo FILE. Declarando um arquivo: FILE *nome; No entanto, declará-lo não indica que ele está pronto para ser usado. É preciso abri-lo. Quando terminar de usar, fechá-lo. O protótipo FILE é definido na biblioteca stdio.h. Ela também define algumas macros relevantes para arquivos: NULL: ponteiro nulo. EOF: fim de arquivo (end of file). FOPEN MAX: número máximo de arquivos abertos. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 11 / 33
Abrindo um Arquivo A função fopen() abre um stream e associa um arquivo a ela. É através dela que dizemos que arquivo usar. Ela retorna um ponteiro do tipo FILE ou NULL (caso não consiga abrir). Assinatura: FILE *fopen(const char *nomearq, const char *modo); Primeiro parâmetro: string que fornece o nome do arquivo (constante ou variável). Segundo parâmetro: string constante que fornece o modo de abertura. Existem diversos modos de abertura de arquivo. Os mais comuns são: modo de leitura ( r ) e modo de escrita ( w ) para stream de texto. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 12 / 33
Modos de Abertura de Arquivo Os valores legais para modo são: 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 Abre um arquivo binário para escrita. a Anexa a um arquivo binário. r+ Abre um arquivo texto para leitura ou escrita. w+ Cria um arquivo texto para leitura ou escrita. a+ Anexa ou cria um arquivo texto para leitura ou escrita. r+b Abre um arquivo binário para leitura ou escrita. w+b Cria um arquivo binário para leitura ou escrita. a+b Anexa ou cria um arquivo binário para leitura ou escrita. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 13 / 33
Abrindo um Arquivo: Exemplo 1 Exemplo de um trecho para a abertura de um arquivo texto existente: FILE *arquivo; arquivo = fopen("teste.txt", "r"); Ou de uma forma melhor: FILE *arquivo; arquivo = fopen("teste.txt", "r"); if(arquivo == NULL){ printf("arquivo nao pode ser aberto!\n"); exit(1); } Neste último caso, será testado se o arquivo pode ser aberto. Caso não possa, o programa exibe uma mensagem e é abortado pela função exit(). Uma possível causa para o retorno NULL é não encontrar o arquivo, por exemplo. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 14 / 33
Abrindo um Arquivo: Exemplo 2 Exemplo de um trecho para a criação de um arquivo texto: FILE *arquivo; arquivo = fopen("teste2.txt", "w"); Ou de uma forma melhor: FILE *arquivo; arquivo = fopen("teste2.txt", "w"); if(arquivo == NULL){ printf("arquivo nao pode ser aberto!\n"); exit(1); } Neste último caso, será testado se o arquivo pode ser criado. CUIDADO: se houver um arquivo com o mesmo nome, ele será apagado! Retornará NULL, por exemplo, se o programa não tiver permissão para criar tal arquivo. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 15 / 33
Fechando um Arquivo Um arquivo que foi aberto deve ser fechado através da função fclose(). O fechamento do arquivo permite escrever todos os dados definitivamente no arquivo. Também permite liberar o bloco de controle do arquivo. Sistema operacional limite um número máximo de arquivos abertos simultaneamente. É conveniente fechar o arquivo assim que terminar de usá-lo. Permite a reutilização de streams. Assinatura: int fclose(file *fp); Parâmetro: ponteiro para o arquivo (retornado no fopen). Função retorna 0 se operação de fechamento foi bem sucedida. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 16 / 33
Abrindo e Fechando arquivo: Exemplo 3 Este programa espera o usuário digitar o nome de um arquivo válido e depois o fecha. 1 #include <stdio.h> 2 3 int main(int argc, char * argv[]){ 4 FILE *arquivo; 5 char nome_arquivo[100]; 6 7 do{ 8 printf("entre com o nome de um arquivo válido: "); 9 scanf("%s", nome_arquivo); 10 arquivo = fopen(nome_arquivo, "r"); 11 } while(arquivo == NULL); 12 13 // Faz algo com o arquivo. 14 15 fclose(arquivo); 16 return(0); 17 } Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 17 / 33
Lendo de um Arquivo Uma vez aberto para leitura, um arquivo pode ser lido. A leitura é realizada sequencialmente. Lembre-se: estamos lendo de um fluxo de dados. Após ler um conjunto de caracteres, os próximos são indicados pelo restante na sequência. Existem funções para leitura de caracteres e para leitura de strings. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 18 / 33
Lendo de um Arquivo Para ler caracteres: fgetc() tem assinatura: int fgetc(file *stream); Retorna o caractere lido (uso de cast int). Para ler string: fgets() tem assinatura: char *fgets(char *s, int size, FILE *stream); Retorna a string ou NULL. fscanf() tem assinatura: int fscanf(file *stream, const char *format,...); Retorna o número de caracteres lidos ou EOF (-1). Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 19 / 33
Lendo de um Arquivo: Exemplo 4 Usando fgetc(): lê caractere por caractere do arquivo e os escreve na tela. 1 #include <stdio.h> 2 #include <stdlib.h> // Para funcao exit(). 3 int main(int argc, char * argv[]){ 4 FILE *fp; 5 char ch; 6 7 fp = fopen("teste.txt", "r"); 8 if(fp == NULL){ 9 printf("o arquivo não pode ser aberto.\n"); 10 exit(1); 11 } 12 ch = fgetc(fp); 13 while(ch!= EOF){ 14 printf("%c", ch); 15 ch = fgetc(fp); 16 } 17 fclose(fp); 18 return(0); 19 } Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 20 / 33
Lendo de um Arquivo: Exemplo 5 Usando fgets(): lê string de tamanho 100 do arquivo (até quebra de linha ou EOF) e as escreve na tela. 1 #include <stdio.h> 2 #include <stdlib.h> // Para funcao exit(). 3 int main(int argc, char * argv[]){ 4 FILE *fp; 5 char str[100]; 6 7 fp = fopen("teste.txt", "r"); 8 if(fp == NULL){ 9 printf("o arquivo não pode ser aberto.\n"); 10 exit(1); 11 } 12 while(fgets(str, 100, fp)!= NULL){ 13 printf("%s", str); 14 } 15 fclose(fp); 16 return(0); 17 } Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 21 / 33
Lendo de um Arquivo: fscanf() A função fscanf() é semelhante à scanf(). Por padrão, ela lê conjunto de caracteres até encontrar espaço, tabulação ou quebra de linha. Deste modo, esta função lê apenas palavra por palavra, ignorando caracteres de espaço, tabulação ou quebra de linha. Por esta razão, não é boa para representar fielmente o que há no arquivo. Usada principalmente para ler valores quando se conhece o formato dele. Por exemplo: sabe-se que o arquivo tem apenas valores inteiros linha a linha. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 22 / 33
Lendo de um Arquivo: Exemplo 6 Ler um vetor de inteiros de um arquivo com no máximo 100 valores. 1 #include <stdio.h> 2 #include <stdlib.h> // Para funcao exit(). 3 int main(int argc, char * argv[]){ 4 FILE *fp; 5 int vet[100], i, n; 6 7 fp = fopen("vetor.txt", "r"); 8 if(fp == NULL){ 9 printf("o arquivo não pode ser aberto.\n"); 10 exit(1); 11 } 12 i = 0; 13 while(fscanf(fp, "%d", &vet[i]) > 0) i++; // EOF < 0 14 n = i; 15 printf("tamanho do vetor: %d\n", n); 16 for(i=0; i<n; i++) printf("vet[%d]: %d\n", i, vet[i]); 17 fclose(fp); 18 return(0); 19 } Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 23 / 33
Lendo de um Arquivo: Exemplo 6 Para arquivo: 1 4 3 2-7 Saída é: Tamanho do vetor: 5 vet[0]: 1 vet[1]: 4 vet[2]: 3 vet[3]: 2 vet[4]: -7 Para arquivo: 1 4 3 2-7 Saída será a mesma do anterior. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 24 / 33
Lendo de um Arquivo: Exemplo 7 Ler uma matriz de inteiros de um arquivo com no máximo 100 100 valores. O arquivo possui as dimensões da matriz separado por espaço, na primeira linha. 1 #include <stdio.h> 2 #include <stdlib.h> // Para funcao exit(). 3 int main(int argc, char * argv[]){ 4 FILE *fp; 5 int mat[100][100], i, j, m, n; 6 7 fp = fopen("matriz.txt", "r"); 8 if(fp == NULL){ 9 printf("o arquivo não pode ser aberto.\n"); 10 exit(1); 11 } 12 fscanf(fp, "%d %d", &m, &n); 13 for(i=0; i<m; i++) 14 for(j=0; j<n; j++) 15 fscanf(fp, "%d", &mat[i][j]); 16 printf("tamanho da matriz: %d x %d\n", m, n); 17 for(i=0; i<m; i++){ 18 for(j=0; j<n; j++) 19 printf("%4d", mat[i][j]); 20 printf("\n"); 21 } 22 fclose(fp); 23 } Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 25 / 33
Lendo de um Arquivo: Exemplo 7 (cont.) Para arquivo com a matriz: 4 3 2-1 0 3 4 2 3 5 7-1 0 1 Saída é: Tamanho da matriz: 4 x 3 2-1 0 3 4 2 3 5 7-1 0 1 Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 26 / 33
Escrevendo em um Arquivo Uma vez aberto para escrita, dados podem ser armazenados em um arquivo. A escrita também é realizada sequencialmente. Lembre-se: estamos escrevendo em um fluxo de dados. Caracteres são escritos um após o outro. Existem funções para escrita de caracteres e para escrita de strings. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 27 / 33
Escrevendo em um Arquivo Para escrever caracteres: fputc() tem assinatura: int fputc(int c, FILE *stream); Primeiro parâmetro é o caractere (cast unsigned char). Retorna o caractere escrito (uso de cast int) ou EOF no caso de erro. Para escrever string: fputs() tem assinatura: int fputs(const char *s, FILE *stream); Escreve a string sem o terminador nulo ( \0 ). Retorna um número não negativo em caso de sucesso. fprintf() tem assinatura: int fprintf(file *stream, const char *format,...); Semelhante ao printf, mas escrevendo em stream. Retorna o número de caracteres escritos ou um valor negativo em caso de erro. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 28 / 33
Escrevendo em um Arquivo: Exemplo 8 Usando fputc(): lê caractere por caractere do tela e os escreve no arquivo até digitar $. 1 #include <stdio.h> 2 #include <stdlib.h> // Para funcao exit(). 3 int main(int argc, char * argv[]){ 4 FILE *fp; 5 char ch; 6 7 fp = fopen("teste_saida1.txt", "w"); 8 if(fp == NULL){ 9 printf("o arquivo não pode ser aberto.\n"); 10 exit(1); 11 } 12 ch = fgetc(stdin); 13 while(ch!= $ ){ 14 fputc(ch, fp); 15 ch = fgetc(stdin); 16 } 17 fclose(fp); 18 return(0); 19 } Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 29 / 33
Escrevendo em um Arquivo: Exemplo 9 Usando fputs(): escreve (no fim do arquivo) strings de tamanho máximo 100 no arquivo, até ser digitado $ no início de uma linha. 1 #include <stdio.h> 2 #include <stdlib.h> // Para funcao exit(). 3 int main(int argc, char * argv[]){ 4 FILE *fp; 5 char str[100]; 6 7 fp = fopen("teste_saida1.txt", "a"); 8 if(fp == NULL){ 9 printf("o arquivo não pode ser aberto.\n"); 10 exit(1); 11 } 12 fgets(str, 100, stdin); 13 while(str[0]!= $ ){ 14 fputs(str, fp); 15 fgets(str, 100, stdin); 16 } 17 fclose(fp); 18 return(0); Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 30 / 33
Escrevendo em um Arquivo: Exemplo 10 Usando fprintf(): imprimir valores de um vetor de reais formatado. 1 #include <stdio.h> 2 #include <stdlib.h> // Para funcao exit(). 3 int main(int argc, char * argv[]){ 4 FILE *fp; 5 int i; 6 float vet[5] = {4.3, 2.0/3.0, 0.943, 17.0/8.0, 0}; 7 8 fp = fopen("vetor_saida.txt", "w"); 9 if(fp == NULL){ 10 printf("o arquivo não pode ser aberto.\n"); 11 exit(1); 12 } 13 fprintf(fp, "%5.2f", vet[0]); 14 for(i=1; i<5; i++) 15 fprintf(fp, " %5.2f", vet[i]); 16 fclose(fp); 17 return(0); 18 } Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 31 / 33
Streams Padrão Sempre que um programa em C começa, 3 streams são abertas automaticamente. stdin: entrada padrão, stdout: saída padrão, e stderr: saída de erro padrão. Entrada padrão geralmente é associada à leitura do console via teclado. Saída padrão geralmente é associada à escrita no console via teclado. Saída de erro padrão também geralmente é associada à escrita no console via teclado. Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 32 / 33
Streams Padrão (II) Podemos usar os seguintes comandos para leitura do teclado (exemplo para inteiro): lê string até espaço: scanf( %d, &n); lê string até espaço: fscanf(stdin, %d, &n); lê string de tamanho 100: fgets(s, 100, stdin); lê apenas 1 caractere: fgetc(c, stdin); Podemos usar os seguintes comandos para escrever na tela (exemplo para inteiro): escreve string formatada: printf( %d, n); escreve string formatada: fprintf(stdout, %d, n); escreve string: fputs(s, stdout); escreve apenas 1 caractere: fputc(c, stdout); Fernanda Passos (UFF) Manipulação de Arquivos Programação de Computadores IV 33 / 33