Академический Документы
Профессиональный Документы
Культура Документы
ARQUIVOS EM C
Existem dois conjuntos de funes de E/S com arquivos na linguagem C. Num primeiro ponto, tem-se a E/S ANSI (com buffer ou formatada) e, em termos mais especficos, tem-se a E/S UNIX (sem buffer ou no formatada). Uma nfase maior dada ao primeiro conjunto pela portabilidade deste sistema de entrada e sada com arquivos. Existem dois tipos possveis de acesso a arquivos na linguagem C : sequencial (lendo um registro aps o outro) e aleatrio (posicionando-se diretamente num determinado registro). O sistema de arquivos na linguagem C definido para manipular uma srie de dispositivos, tais como terminais, acionadores de disco e outros. Estes dispositivos so vistos como arquivos lgicos em C, denominados STREAM (abstrao do dispositivo). O dispositivo real denominado ARQUIVO (impressora, disco, console e outros). Um STREAM associado a um ARQUIVO por uma operao de abertura do arquivo e, a partir da associao, todas as demais operaes de escrita e leitura podem ser realizadas. A Tabela 1 apresenta as principais funes da linguagem C para manipulao de arquivos. Funo Ao Abre um arquivo Fecha um arquivo Escreve um caractere em um arquivo L um caractere de um arquivo Posiciona em um registro de um arquivo Efetua impresso formatada em um arquivo Efetua leitura formatada em um arquivo Verifica o final de um arquivo Escreve tipos maiores que 1 byte em um arquivo L tipos maiores que 1 byte de um arquivo Escreve uma cadeia de caracteres em um arquivo L uma cadeia de caracteres em um arquivo Posiciona o cursor no incio do arquivo Apaga um arquivo Altera o nome de um arquivo
fopen() fclose () fputc() fgetc() fseek() fprintf() fscanf() feof() fwrite() fread() fputs() fgets() rewind() remove() rename()
FILE *Arquivo;
Pela declarao anterior, passa a existir uma varivel de nome Arquivo, que ponteiro para um arquivo. O ponteiro de arquivo une o sistema de E/S a um buffer. O ponteiro no aponta diretamente para o arquivo em disco, mas contm informaes sobre o arquivo, incluindo nome, status (aberto, fechado e outros) e posio atual sobre o arquivo.
1) ABRINDO UM ARQUIVO
A funo que abre um arquivo em C a funo fopen(), que devolve o valor NULL (nulo) ou um ponteiro associado ao arquivo, devendo ser passado para funo o nome fsico do arquivo e o modo como este arquivo deve ser aberto. Arquivo = fopen ("texto.txt","w");
Com a instruo acima, est sendo aberto um arquivo de nome "texto.txt", no disco, habilitado apenas para escrita (w-write). Utilizando-se tcnicas de verificao, pode-se codificar a instruo acima da seguinte maneira:
if ((Arquivo = fopen("texto.txt","w")) == NULL) { printf("\n Arquivo TEXTO.TXT no pode ser aberto : TECLE ALGO"); getch(); }
Alm do modo de escrita, a linguagem C permite o uso de alguns valores padronizados para o modo de manipulao de arquivos, conforme mostra a Tabela 2
Modo "r" Significado
Abre um arquivo texto para leitura. O arquivo deve existir antes de ser aberto. Abrir um arquivo texto para gravao. Se o arquivo no existir, ele ser criado. Se j existir, o "w" contedo anterior ser destrudo. Abrir um arquivo texto para gravao. Os dados sero adicionados no fim do arquivo ("append"), se "a" ele j existir, ou um novo arquivo ser criado, no caso de arquivo no existente anteriormente. "rb" Abre um arquivo binrio para leitura. Igual ao modo "r" anterior, s que o arquivo binrio. "wb" Cria um arquivo binrio para escrita, como no modo "w" anterior, s que o arquivo binrio. "ab" Acrescenta dados binrios no fim do arquivo, como no modo "a" anterior, s que o arquivo binrio. "r+" Abre um arquivo texto para leitura e gravao. O arquivo deve existir e pode ser modificado. Cria um arquivo texto para leitura e gravao. Se o arquivo existir, o contedo anterior ser destrudo. "w+" Se no existir, ser criado. Abre um arquivo texto para gravao e leitura. Os dados sero adicionados no fim do arquivo se ele "a+" j existir, ou um novo arquivo ser criado, no caso de arquivo no existente anteriormente. "r+b" Abre um arquivo binrio para leitura e escrita. O mesmo que "r+" acima, s que o arquivo binrio. "w+b" Cria um arquivo binrio para leitura e escrita. O mesmo que "w+" acima, s que o arquivo binrio. Acrescenta dados ou cria uma arquivo binrio para leitura e escrita. O mesmo que "a+" acima, s que "a+b" o arquivo binrio
Tabela 2 - Modos para manipulao de arquivos MODO BINRIO X MODO TEXTO Em modo texto, cada caracter (digito, letra, ou caracter especial) ocupa um byte. Ou seja, para gravar o nmero 32153, que em memria ocuparia 2 bytes, em arquivo modo texto so necessrios 5 bytes. O modo binrio mais eficiente para guardar nmeros pois ocupa menos espao.
2) FECHANDO UM ARQUIVO
Para o esvaziamento do buffer de um arquivo utilizada a funo fclose(), que associa-se diretamente ao nome lgico do arquivo (STREAM).
fclose (Arquivo);
b) fprintf : Grava dados formatados no arquivo, de acordo com o tipo de dados (float, int, ...). Similar ao printf, porm ao invs de imprimir na tela, grava em arquivo c) fwrite : Grava um conjunto de dados heterogneos (struct) no arquivo. SINTAXE DO PUTC: putc (caracter, arquivo); /* Grava o contedo da varivel caracter no "arquivo" */
Vejamos o exemplo de putc, num programa que simula um editor de texto, bem simples, que grava em arquivo um texto que vai sendo digitado via teclado at que o usurio finalize com um CTRL+Z
#include <stdio.h> #include <conio.h> void main () { FILE *Arquivo; char Caractere, Nome[20]; clrscr(); printf("Nome do arquivo? "); fflush(stdin); gets(Nome); Arquivo = fopen (Nome,"w"); if (Arquivo == NULL) { printf ("Erro abertura do Arquivo : %s. Tecle algo !\n",Nome); getch(); } else { do { Caractere = getche(); if (Caractere == 13) { \* teclou enter *\ putc('\n',Arquivo); \* grava um \n no arquivo printf("\n"); \* pular linha na tela pois getche no faz isso com } else { putc(Caractere,Arquivo); } } while (Caractere != 26); // CTRL + Z para encerrar } fclose(Arquivo); printf("\n Fim da digitao do texto !" ); getch(); }
Programa 1 Manipulao de arquivo-texto para escrita OBS : Mais adiante veremos a sintaxe e o exemplo de uso de fprintf e fwrite
enter */
getc retorna EOF caso encontre o fim-de-arquivo ou em caso de erro na leitura Vejamos o exemplo de getc, num programa que simula um "mostrador" de texto, bem simples, que l arquivo texto j gravado em disco e vai mostrando na tela :
#include <stdio.h> #include <conio.h> void main () { FILE *Arquivo; char Nome[20]; char Caractere; clrscr (); printf ("Nome do arquivo? "); fflush(stdin); gets (Nome); Arquivo = fopen (Nome,"r"); if (Arquivo == NULL) { printf ("Erro abertura do Arquivo : %s. Tecle algo !\n",Nome); getch(); } else { Caractere = getc(Arquivo); while (Caractere != EOF) { printf("%c", Caractere); Caractere = getc(Arquivo); } fclose (Arquivo); fprintf("\n *** fim de texto *** Tecle algo !") getch (); } }
Programa 2 Manipulao de arquivo-texto para leitura OBS : Mais adiante veremos a sintaxe e o exemplo de uso de fscanf e fread
EXERCICIOS : a) Escreva um programa que faa a cpia de um arquivo origem, gerando um para um arquivo destino onde todos os caracteres estejam em minsculo. A funo tolower converte um caracter para minsculo, est na biblioteca ctype.h e possui a seguinte sintaxe : a = tolower(b); A instruo acima converte o caracter da varivel b para minsculo e retorna para a varivel a, onde a e b podem ser a mesma varivel. b) Escreva um programa para contar quantas palavras existem num arquivo texto. Lembre-se de considerar como separador de palavra os caracteres : '\t' - caracter de tabulao '\n' quebra de linha ' ' - espao em branco
tot_bytes = fprintf (arqfunc, "%d %c %f ", idade, sexo, salario); obs. : Os formatos devem ser separados por espaos em branco
6 /* programa exemplo com fprintf */ #include <stdio.h> #include <conio.h> #include <string.h> void main() { FILE *arqfunc; int sexo; int codfunc, idade; float salario; arqfunc = fopen("FUNCIONA.DAD", "w"); if (arqfunc == NULL) { printf("\nArquivo FUNCIONA.DAD nao pode ser criado."); printf("\nErro Grave ! Tecle algo !"); getch(); } else { clrscr(); do { printf("\n Digite o codigo do funcionario ou um numero negativo \ para encerrar : "); scanf("%d", &codfunc); if (codfunc > 0){ printf("\n Digite o sexo [M ou F] : "); sexo = getche(); printf("\n Digite a idade : "); scanf("%d", &idade); printf("\n Digite o salario : "); scanf("%f", &salario); /* a instrucao abaixo grava os dados no arquivo */ fprintf(arqfunc, "%d %c %d %f ", codfunc, sexo, idade, salario); } } while ( codfunc > 0); fclose (arqfunc); } }
O programa abaixo l o arquivo gravado com o programa anterior, utilizando fscanf e mostra os dados na tela Veja que deve-se usar a mesma seqncia de leitura que se usou para gravar : O Primeiro nome, depois o sexo, a idade e o salrio. Veja ainda que o nome lido com fgets devido ao problema j exposto anteriormente sobre o fscanf com %s
/* programa exemplo com fscanf #include <stdio.h> #include <conio.h> #include <string.h> #define LETRAS 60 void main() { FILE *arqfunc; char sexo, aux; int codfunc, idade, float salario;
i = 0;
7 clrscr(); arqfunc = fopen("FUNCIONA.DAD", "r"); if (arqfunc == NULL) { printf("\nArquivo FUNCIONA.DAD nao pode ser aberto."); printf("\nErro Grave ! Tecle algo !"); getch(); } else { aux = fscanf(arqfunc, "%d %c %d %f",&codfunc, &sexo, &idade, &salario); while (aux != EOF) { i = i + 1; printf("\n Dados do %d funcionario : \n ", i); printf("\n Codigo : %d Sexo : %c", codfunc, sexo); printf("\n Idade ...: %d Salario : %8.2f", idade, salario); printf("\n------------------------------------- Tecle algo !"); getch(); aux = fscanf(arqfunc, "%d %c %d %f",&codfunc, &sexo, &idade, &salario); } fclose (arqfunc); printf("\n *** FIM getch(); } }
B) LENDO E GRAVANDO ESTRUTURAS Alm da manipulao de arquivos do tipo texto, pode-se ler e escrever estruturas maiores que 1 byte, usando as funes fread() e fwrite(), conforme os prottipos seguintes.
fread (buffer, tamanhoembytes, quantidade, ponteirodearquivo) fwrite (buffer, tamanhoembytes, quantidade, ponteirodearquivo)
O buffer um endereo de memria da estrutura de onde deve ser lido ou onde devem ser escritos os valores (fread() e fwrite(), respectivamente). O tamanhoembytes um valor numrico que define o nmero de bytes da estrutura que deve ser lida/escrita. A quantidade o nmero de estruturas que devem ser lidas ou escritas em cada processo de fread ou fwrite. O ponteirodearquivo o ponteiro do arquivo de onde deve ser lida ou escrita uma estrutura. Normalmente quando trabalhos com arquivos (no texto), utilizamos arquivos de estruturas (struct). Podemos por exemplo falar num arquivo de CLIENTES, onde cada cliente possui NOME, RG, ENDERECO E TELEFONE. Na linguagem de ARQUIVOS, cada OCORRNCIA de cliente num arquivo chamado de REGISTRO e cada informao dentro do REGISTRO do cliente chamada de CAMPO. Num arquivo com 10 clientes, dizemos que h 10 registros. No exemplo acima, dizemos que os campos do REGISTRO de Clientes so : NOME, RG, ENDEREO e TELEFONE.
OBS. : A funo sizeof retorna a quantidade de bytes de um determinado tipo ou varivel Exemplo :
sizeof(int) retorna 2 de acordo com o tipo de mquina
Exemplos :
#include <stdio.h> #include <conio.h> #define LETRAS 50 struct Tcliente { char situacao; int codigo; char nomecli[LETRAS]; char fone [15]; char sexo; float limite; }; // prototipos void Entrada (FILE *); char ValidaSexo(); char Validaresp(); // ================================================================= void main() { FILE *cliente; char verro = 'N'; char arqcli [] = {"CLIENTE.DAD"}; cliente = fopen(arqcli, "rb+"); if (cliente == NULL) { printf(" \n Arquivo %s Nao existe : Tecle algo para criar agora ! ", arqcli); getch(); if ((cliente = fopen(arqcli, "wb+")) == NULL) { verro = 'S'; printf(" \n Erro grave ! Nao consigo criar o arquivo %s !!!", arqcli); getch(); } } if (verro == 'N') { Entrada(cliente); fclose (cliente); } } // entrada de dados gravando direto em arquivo void Entrada (FILE * cliente) { int retorno; struct Tcliente Vcli; char vresp; do { clrscr(); printf("\n Digite o Codigo [Zero encerra] : " ); scanf("%d", &Vcli.codigo); if (Vcli.codigo != 0) { printf(" \n Digite o nome : "); fflush(stdin); gets(Vcli.nomecli);
// // // // // //
situacao do registro : excluido codigo do sujeito nome do sujeito fone do sujeito sexo limite de credito
ou nao ?
9 Vcli.sexo = ValidaSexo(); printf(" \n Digite o Fone : " ); gets(Vcli.fone); printf(" \n Digite o Limite de Credito do cliente : "); scanf("%f", &Vcli.limite); vresp = Validaresp(); if (vresp == 'S') { retorno = fwrite (&Vcli, sizeof(struct Tcliente) ,1,cliente); // fwrite retorna a quantidade de itens gravados (NAO BYTES) if (retorno == 1) { printf(" \n Gravacao ok ! "); getch(); } else { printf (" \n Problemas : Gravacao nao efetuada !!!" ); getch(); } } } } while (Vcli.codigo != 0); } // validar o sexo char ValidaSexo() { char vsexo; do { printf(" \n Digite o Sexo [M ou F] : " ); vsexo = getche(); } while (vsexo != 'F' && vsexo != 'M'); return vsexo; } // validar a respostar // validar o sexo char Validaresp() { char vresp; do { printf(" \n Confirma Inclusao [S ou N] ? " ); vresp = getche(); } while (vresp != 'S' && vresp != 'N'); return vresp; }
10
// // // // // //
situacao do registro : excluido codigo do sujeito nome do sujeito fone do sujeito sexo limite de credito
ou nao ?
// Le dados de um arquivo e imprime na Tela void Le_Imprime (FILE * cliente) { int retorno, cont = 0; struct Tcliente Vcli; retorno = fread(&Vcli, sizeof(struct Tcliente), 1, cliente); // fread retorna a quantidade de itens retornados ... clrscr(); while ( retorno == 1) { cont++; printf("\n\n DADOS DO CLIENTE %d \n", cont); printf("\n Codigo : %d", Vcli.codigo); printf("\n Nome ..: %s", Vcli.nomecli); printf("\n Sexo ..: %c", Vcli.sexo); printf("\n Fone ..: %s", Vcli.fone); printf("\n Limite : %.2f", Vcli.limite); retorno = fread(&Vcli, sizeof(struct Tcliente), 1, cliente); } printf(" \n\n %d clientes cadastrados ", cont); getch(); }