Prévia do material em texto
1 Arquivos na linguagem C Introdução Fluxos de Dados e Arquivos Funções de Entrada e Saída Abrindo um Arquivo Lendo e Escrevendo Caracteres Entrada e Saída Formatada Exercícios 2 Introdução � Funções para E/S de dados � Em C não existem comandos de Entrada e Saída � estas tarefas são executadas por funções armazenadas em bibliotecas específicas. � Fluxos de Dados � A linguagem C utiliza o conceito de fluxo (stream) de dados para isolar os programadores dos problemas de manipular os vários tipos de dispositivos de armazenamento e seus diferentes formatos. � Todos os diferentes sistemas de arquivos se comportam da mesma maneira quando manipulados como um fluxo contínuo de dados. � Dados podem ser manipulados em dois diferentes tipos de fluxos: fluxos de texto e fluxos binários. 3 Fluxos de Dados Fluxos de Texto � Composto por uma seqüência de caracteres, que pode ou não ser dividida em linhas terminadas por um caractere de final de linha. � Um detalhe que deve ser considerado é que na última linha não é obrigatório o caractere de fim de linha. � É comum se trabalhar com fluxo de dados padrão: stdin, para entrada de dados e stdout para saída de dados. Fluxo Binário � Composto por uma seqüência de bytes lidos, sem tradução, diretamente do dispositivo externo. 4 Arquivo em C � Arquivo pode ser qualquer dispositivo de Entrada e Saída como por exemplo: impressora, teclado, disquete, disco rígido, etc. Programas vêem os arquivos através de fluxos. � Para que um determinado arquivo seja associado a um determinado fluxo é necessário que o arquivo seja aberto. Após esta operação o programa pode utilizar os dados armazenados no arquivo. � Operações comuns em arquivos são: � abertura e fechamento de arquivos; � exclusão de um arquivo; � leitura e escrita de caracteres; � indicação de que o fim do arquivo foi atingido; � Fechamento de um arquivo 5 Funções de Entrada e Saída armazenadas na biblioteca stdio.h Função Descrição fopen() Abre um arquivo putc(), fputc() Escreve um caractere em um arquivo getc(), fgetc() Lê um caractere de um arquivo fprintf() Equivalente a printf(), usando cadeia de caracteres sscanf() Equivalente a scanf(), usando cadeia de caracteres fscanf() Equivalente a scanf(), usando cadeia de caracteres fseek() Posiciona o arquivo em um ponto específico rewind() Posiciona o arquivo no início feof() Verifica fim do arquivo ferror() Verifica a ocorrência de erro fread() Leitura de dados no modo binário fwrite() Escrita de dados no modo binário 6 Criação de Arquivo em C � Para ter acesso aos dados em um arquivo �definir um ponteiro do tipo especial FILE. � Um ponteiro deste tipo permite que o programa tenha acesso a uma estrutura que armazena informações importantes sobre o arquivo. � Para definir uma variável deste tipo usar � FILE *arq; � onde arq é o ponteiro que será usado para executar as operações no arquivo. 7 Abrindo um Arquivo em C � Antes de qualquer operação ser executada com o arquivo, ele deve ser aberto. � Esta operação associa um fluxo de dados a um arquivo. Um arquivo pode ser aberto de diversas maneiras: leitura, escrita, leitura/escrita, adição de texto, etc. � A função utilizada para abrir o arquivo é chamada fopen() e tem o seguinte protótipo: FILE *fopen (const char *parq, const char *modo) � onde parq é um ponteiro de arquivo para o arquivo a ser manipulado e � modo é um ponteiro para uma cadeia de caracteres que define a maneira como o arquivo vai ser aberto. � função retorna um ponteiro nulo (NULL) se o arquivo não puder ser aberto. 8 Modos de abertura de arquivos Modo Descrição r Abre um arquivo texto para leitura w Cria um arquivo texto para escrita a Adiciona texto ao fim de um arquivo texto rb Abre um arquivo binário para leitura wb Abre um arquivo binário para escrita ab Anexa a um arquivo binário r+ Abre um arquivo texto para leitura/escrita w+ Cria um arquivo texto para leitura/escrita a+ Cria ou anexa a um arquivo texto para leitura/escrita r+b Abre um arquivo binário para leitura/escrita r+b Cria um arquivo binário para leitura/escrita a+b Anexa a um arquivo binário para leitura/escrita 9 Exemplos � Exemplo -1: FILE *clientes, *produtos; // clientes e produtos são ponteiros p/ arquivos clientes = fopen (“clientes.txt”, “r”); // Aberto só para leitura produtos = fopen (“novos_produtos.dat”, “w”); //Aberto só para escrita � Exemplo –2 arq=fopen ("c:/Thelma/MC326/dados2.txt","r"); arq= fopen ("../dados2.dat","r"); � Detalhes sobre o Retorno da função fopen � Retorna ponteiro para arquivo � se encontrar � Retorna Valor NULL � se não encontrar o arquivo 10 Abertura de arquivos - Exemplo Uma maneira comum de abrir um arquivo é escrevendo-se o seguinte comando: FILE *pa; if (( pa = fopen ("arquivo.txt", "w")) == NULL ) { printf(" Arquivo não pode ser aberto “); exit(1); } � Se um arquivo for aberto com modo de escrita � Todo o seu conteúdo anterior será apagado � Caso o arquivo não exista ele será criado. 11 Fechando um Arquivo � Um arquivo aberto por meio da função fopen() deve ser fechado com a função fclose() cujo protótipo é int fclose (FILE *parq); � onde parq é um ponteiro de arquivo para o arquivo que deve ser fechado. � O retorno do valor zero significa que a operação foi executada com êxito, qualquer outro valor implica em erro. � fclose() implica em escrita no arquivo de qualquer dado que ainda não tenha sido escrito. � Este ponto é importante de ser considerado porque em UNIX uma operação de escrita em um arquivo não ocorre imediatamente a emissão da ordem de escrita. O sistema operacional pode executar a ordem no momento que achar mais conveniente. 12 Fim e início de Arquivo Fim de arquivo � A função feof() serve para indicar que o final de um arquivo foi encontrado. O protótipo da função é o seguinte: int feof(FILE *parq) Volta ao Início � A função rewind() recoloca o indicador de posição de arquivo no inicio do arquivo. Uma operação semelhante ao que fazemos em uma fita cassete de música ou vídeo. O protótipo da função é o seguinte: void rewind(FILE *parq) Observações: � o arquivo deve estar aberto em um modo que permita a execução das operações desejadas. Por exemplo, um arquivo aberto somente para escrita e em seguida rebobinado para o início, não irá permitir outra operação que não seja escrita. 13 Ler e escrever Cadeias de Caracteres � As funções fgets() e fputs() servem para ler e escrever cadeias de caracteres em arquivos. i Os protótipos das funções são: int fputs(char *str, FILE *parq); int fgets(char *str, int comp, FILE *parq); � A função fputs() escreve a cadeia de caracteres apontada por str no fluxo apontado por parq e o código correspondente à EOF será retornado se ocorrer um erro. � A função fgets() lê uma cadeia de caracteres do fluxo especificado até que um caractere de nova linha seja encontrado ou comp-1 caracteres sejam lidos. Caso ocorra um erro na leitura da cadeia o ponteiro str recebe o valor NULL 14 Exemplo /* Programa que escreve e em seguida le caracteres de um arquivo. */ #include<stdio.h> #include<stdlib.h> #define MAX 80 int main (void ) { char linha[MAX]; FILE *pa; char *nome = "texto.txt"; /* Abre o arquivo para leitura e escrita */ if (( pa = fopen(nome, "w+")) == NULL) { printf("\n\nNao foi possivel abrir o arquivo.\n"); exit(1); } /* Le linha e grava no arquivo */ gets(linha); while (!feof(stdin)) { strcat(linha, "\n"); fputs(linha, pa); gets(linha);} 15 Exemplo (cont) /* volta ao inicio do arquivo e le caracteres*/ rewind(pa); printf(“\n agora vou ler.\n"); fgets(linha, MAX, pa); while (!feof(pa)){ printf("%s",linha); fgets(linha, MAX, pa); } fclose(pa); getchar();/* Espera o usuario digitar alguma coisa */ 16 Lendo e Escrevendo Arquivos Binários As funções fread e fwrite são empregadas para leitura e escrita de dados em modo binário. Os protótipossão: size_t fread (void *ptr, size_t size, size_t nmemb, FILE *parq); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *parq); A função fread lê nmemb elementos de dados, cada um com size bytes de comprimento do fluxo e os coloca na localização apontada por ptr. � Retorna o número de itens que foram lidos com sucesso. Caso ocorra um erro, ou o fim do arquivo foi atingido o valor de retorno é menor do que nmemb ou zero. � Esta função não distingue entre um fim de arquivo e erro, portanto é aconselhável o uso de feof() ou ferror() para determinar que erro ocorreu. A função fwrite escreve nmemb elementos de dados, cada um com size bytes de comprimento, do fluxo apontado por parq obtendo-os da localização apontada por ptr. Fwrite. � Retorna o número de itens que foram lidos com sucesso. � Caso ocorra um erro, ou o fim do arquivo foi atingido o valor de retorno é menor do que nmemb ou zero. 17 Exemplo int main (void ) { /* definição dos valores que serão gravados no arquivo*/ int inum=10;float fnum=2.5;double pi=3.141516; char c='Z'; FILE *pa; char *nome = "texto.txt"; if (( pa = fopen(nome, "w+b")) == NULL) { printf("\n\nNao foi possivel abrir o arq\n"); exit(1); } /* escrevendo no arquivo apontado por pa */ fwrite(&inum, sizeof(int), 1, pa); fwrite(&fnum, sizeof(float), 1, pa); fwrite(pi, sizeof(double), 1, pa); fwrite(&c, sizeof(char), 1,pa); 18 Exemplo /* lendo o arquivo gravado */ rewind(pa); fread(&inum, sizeof(int), 1, pa); fread(&fnum, sizeof(float), 1, pa); fread(π, sizeof(double), 1, pa); fread(&c, sizeof(char), 1, pa); Exibindo os resultados retirados do arquivo */ printf("%d, %f, %lf, %c\n", inum, fnum, pi, c); fclose(pa); exit(0);} 19 Manipulação de arquivos acesso direto e seeking Nos exemplos anteriores, os arquivos foram lidos seqüencialmente. � Cada vez que um registro (uma cadeia de caracteres) é lido, o ponteiro do arquivo avança, e o sistema fica pronto para acessar o próximo dado . � Certas situações exigem buscas e acessos randômicos em arquivos (ponteiro seja posicionado diretamente em uma posição específica), por exemplo o final do arquivo ou no registro de número 10000. � A ação de mover o ponteiro do arquivo diretamente para uma certa posição é chamada seeking (busca, ou posicionamento). � A operação de seeking genérica precisa de no mínimo duas informações: � o identificador do arquivo e � a posição a ser acessada. 20 Manipulação de arquivos acesso direto e seeking � Em C, a função fseek( ) provê o serviço Seu protótipo é: int fseek(FILE *cadeia, long int tam, int pos); retorna a posição no arquivo após deslocamento de tam bytes a partir de pos. tam � n.º de bytes de deslocamento pos �posição de origem do deslocamento. Os valores para pos são os que seguem: SEEK_END SEEK_CUR SEEK_SET Nome Fim do arquivo2 Ponto corrente no arquivo1 Início do arquivo0 significadoValor 21 Exercício Escreva um programa que compare dois arquivos especificados pelo usuário e imprima sempre que os caracteres dos dois arquivos coincidirem. Por exemplo considere os dois arquivos dados abaixo: arquivo1.dat Olá, pessoal! arquivo2.c Oi, como vai? Neste caso, os caracteres na primeira e décima primeira posição são iguais nos dois arquivos. A saída do seu programa deve ser algo como: 1 - O 11 - a 22 Exercício #include <stdio.h> int main() { char f1[256], f2[256]; FILE *fp1, *fp2; int c1, c2; /* abrindo os dois arquivos para leitura */ do { printf("Informe o nome do primeiro arquivo: "); gets(f1); fp1=fopen(f1, "r"); if (fp1==NULL) puts("\nNao e possivel abrir o arquivo especificado!"); } while (fp1==NULL); do { printf("Informe o nome do segundo arquivo: "); gets(f2); fp2=fopen(f2, "r"); if (fp2==NULL) puts("\nNao e possivel abrir o arquivo especificado!");} while (fp2==NULL); 23 Exercício (cont) fseek(fp1, 0, SEEK_SET); fseek(fp2, 0, SEEK_SET); while (1) { c1=fgetc(fp1); c2=fgetc(fp2); if (feof(fp1) || feof(fp2)) break; if (c1==c2) printf("%ld - %c \n", ftell(fp1), c1); } }