246 Arquivo En4dade básica do sistema operacional (SO). Estrutura que armazena informação de forma não volá4l em disposi4vos de memória permanente. Após sua criação, podem ser acessados e modificados por algum programa. Tipos de arquivos Texto (símbolos da tabela ASCII). Documentos. Planilhas. Bancos de dados. Figuras (jpg, bmp, png etc.) Música (wav, mp3, wma, ogg etc.) Filmes (mpg, avi, mov, mp4 etc.) Formatos proprietários. 247
Mo4vação Na execução de um programa os valores das variáveis (inicializadas, lidas e/ou calculadas) são armazenados na memória principal (volá4l). Problemas A informação é perdida quando encerra-se o escopo das variáveis locais. Os dados deixam de exis4r quando encerra-se a execução do programa. As estruturas de dados tem capacidade de armazenamento limitada. Solução Armazenar (salvar) os dados relevantes em disposi4vos de memória permanente: disco rígido, cartões de memória, discos ó4cos, disquete etc. 248 Tipos de arquivos em C Arquivo texto Seqüência de caracteres da tabela ASCII. A informação é agrupada em linhas. Podem ser exibidos na tela e modificados com editores de texto (p. ex., Bloco de notas.) Arquivo binário Os dados são armazenados como seqüências de bits. Ocupam menos espaço. A informação fica criptografada: apenas o programador sabe a estrutura como os dados estão armazenados 249
Como trabalhar com arquivos em programas em C? Realizar as seguintes etapas: 1. Declarar o arquivo. 2. Abrir o arquivo. 3. Executar as operações desejadas no arquivo. 4. Fechar o arquivo. 250 Declaração de arquivos A declaração de um arquivo visa criar uma variável no programa que será associada a um arquivo do SO. A biblioteca stdio.h define a estrutura FILE para tratamento de arquivos pela linguagem C. Todo arquivo deve ser declarado como um ponteiro do 4po FILE: #include <stdio.h> int main() // arq é um ponteiro para arquivos return(0); 251
Abertura de arquivo texto A função fopen() associa uma variável do 4po FILE a um arquivo do SO. Todo arquivo deve ser aberto antes de ser usado. arq = fopen(char *nome, char *modo) nome: string associada ao nome do arquivo. modo: string que define o modo de acesso ao arquivo. Modo de acesso r ou r+ w ou w+ a ou a+ Descrição Abre um arquivo texto apenas para leitura ou leitura e escrita. O arquivo já deverá exis4r antes de ser aberto. Cria um arquivo texto apenas para escrita ou leitura e escrita. Se o arquivo já exis4r, o conteúdo anterior será apagado. Abre um arquivo texto apenas para escrita ou leitura e escrita. Se o arquivo já exis4r, a nova informação será adicionada a par4r do final do arquivo 252 Abertura de arquivo texto Abrir o arquivo texto local dados.txt para leitura: arq = fopen("dados.txt","r"); Abrir o arquivo texto remoto dados.dat para escrita: arq = fopen("z:\\arquivos\\pc-i\\dados.dat","w"); Abrir para adição de dados um arquivo texto informado pelo usuário: char *nomearq; printf("nome do arquivo: "); gets(nomearq); arq = fopen(nomearq,"a"); 253
Abertura de arquivos É aconselhável verificar se a abertura de arquivos foi bem sucedida: #include <stdio.h> int main() // arq é um ponteiro para arquivos arq = fopen("dados.dat", "r"); if (arq == NULL) puts("erro na abertura do arquivo."); system("pause"); exit(0); // encerra a execução do programa return(0); 254 Leitura de arquivo texto Arquivos texto são tratados pelo sistema operacional como seqüências de caracteres. Entretanto, a linguagem C permite que tais caracteres sejam interpretados para outro formato (p. ex., o caractere '1' ou o inteiro 1.) A função fscanf() é u4lizada para a leitura formatada de dados con4dos em um arquivo texto. Sua sintaxe é semelhante à da função scanf(): fscanf(<variável do tipo FILE>, ); Atenção! Você só pode ler de um arquivo que já exista! 255
Leitura de arquivo texto Importante! A leitura de um arquivo é sempre realizada de modo seqüencial. Exemplo: Ler o peso e a altura de uma pessoa a par4r de um arquivo texto. cadastro.dat 1 2 3 82 1.75 int peso; float altura; arq = fopen("cadastro.dat", "r"); 1 fscanf(arq, "%d", &peso); 2 fscanf(arq, "%f", &altura); 3 printf("peso = %d\naltura ; %f\n", peso, altura); 256 Leitura de arquivo texto Exemplo: Ler uma matriz quadrada de ordem 3, cujos elementos inteiros estão armazenados no arquivo texto matriz.dat. matriz.dat 1 2 3 4 5 6 7 8 9 int a[3][3], i, j; arq = fopen("matriz.dat", "r"); for ( i = 0; i < 3; i++ ) for ( j = 0; j < 3; j++ ) fscanf(arq, "%d", &a[i][j]); 257
Escrita em arquivo texto A função fprintf() é u4lizada para a escrita formatada de dados em um arquivo texto. Sua sintaxe é semelhante à da função printf(): fprintf(<variável do tipo FILE>, ); char nome[80]; arq = fopen("amigos.txt", "w"); do printf("informe um nome: "); gets(nome); if (nome[0]!= '\0') fprintf(arq, "%s\n", nome); while ( nome[0]!= '\0' ); 258 Escrita em arquivo texto Exemplo: Escrever na tela e em arquivo texto o fatorial de um número inteiro informado pelo usuário. int i, n; double fat = 1.0; FILE *out; out = fopen("fatorial.txt", "w"); printf("informe um número inteiro positivo: "); scanf("%d", &n); for (i = 1; i <= n; i++) fat = fat * i; printf("%d! = %.0f\n", n, fat); fprintf(out, "%d! = %.0f\n", n, fat); 259
Fechamento de arquivo Para fechar um arquivo previamente aberto, usa-se a função fclose(). #include <stdio.h> int main() // arq é um ponteiro para arquivos arq = fopen(); fclose(arq); Por quê é importante fechar arquivos? Para liberar memória para o sistema operacional. Para gravar efe4vamente as informações em arquivos abertos para escrita. 260 Fim de arquivo Em alguns casos, a quan4dade de dados a ser lida não é definida a priori. Assim, a leitura (e o processamento) da informação deverá ser executada enquanto não se a4ngir o fim do arquivo. Na linguagem C, a função feof() retorna o valor verdadeiro se o fim do arquivo foi alcançado. int peso; float altura; arq = fopen("cadastro.dat", "r"); while (!feof(arq) ) fscanf(arq, "%d %f", &peso, &altura); printf("peso = %3d\tAltura = %4.2f\n", peso, altura); fclose(arq); 261
Leitura e escrita de strings em arquivo texto A linguagem C proporciona funções exclusivas para processamento de strings em arquivos texto. A função fgets(char *str, int tamanho, FILE *arq) lê do arquivo texto arq uma seqüência de tamanho caracteres e a armazena na string str. fgets() Os espaços em branco presentes na seqüência lida serão preservados. Os valores numéricos presentes na seqüência lida serão conver4dos para caracteres. A função fputs(char *str, FILE *arq) escreve no arquivo texto arq a seqüência de caracteres da string str, seguida do caractere '\n' (nova linha). 262 Arquivos binários Nos arquivos binários a informação é armazenada como na memória, ou seja, em seqüências de bits (0 s e 1 s). 1110001101010011101011010101011010010100 0111010100001110101010010101000101011110 0001010011100001010001010110010101000101 1111101010101010101000011011011011101001001010101110010100000000 0010101010100101001010101010100110101001100011010100010000000000 O acesso à informação é mais rápida, pois não há necessidade de conversão para símbolos da tabela ASCII, como ocorre com os arquivos 4po texto. Um arquivo binário é composto por blocos de informação denominados registros. Cada registro é composto por um número inteiro de bytes. 263
Registros O processamento das informações con4das em cada registro de um arquivo binário pode ser feito com o emprego de 4pos seqüenciais ou estruturados. typedef struct int i; char c; umtipo; 1110001101010011101011010101011010010100 0111010100001110101010010101000101011110 0001010011100001010001010110010101000101 1111101010101010101000011011011011101001001010101110010100000000 0010101010100101001010101010100110101001100011010100010000000000 typedef struct char c; float x; char s[3]; outrotipo; 264 Abertura de arquivos binários A função fopen() também é u4lizada para acesso a arquivos binários. Todo arquivo deve ser aberto antes de ser usado. arq = fopen(char *nome, char *modo) nome: string associada ao nome do arquivo. modo: string que define o modo de acesso ao arquivo. Modo de acesso rb ou r+b wb ou w+b ab ou a+b Descrição Abre um arquivo binário apenas para leitura ou leitura e escrita. O arquivo já deverá exis4r antes de ser aberto. Cria um arquivo binário apenas para escrita ou leitura e escrita. Se o arquivo já exis4r, o conteúdo anterior será apagado. Abre um arquivo binário apenas para escrita ou leitura e escrita. Se o arquivo já exis4r, a nova informação será adicionada a par4r do final do arquivo 265
Abertura de arquivos binários Abrir o arquivo binário local dados.bin para leitura: arq = fopen("dados.bin","rb"); Abrir o arquivo binário remoto dados.bin para escrita: arq = fopen("z:\\arquivos\\pc-i\\dados.bin","wb"); Abrir para adição de dados um arquivo binário informado pelo usuário: char *nomearq; printf("nome do arquivo: "); gets(nomearq); arq = fopen(nomearq,"ab"); 266 Leitura de arquivo binário A função fread() é u4lizada para a leitura de registros em um arquivo binário. Sua sintaxe é: fread(&var, numbytes, cont, arq); &var: o endereço da variável onde o registro será armazenado; numbytes: tamanho do registro a ser lido (em bytes); cont: numero de registros a serem lidos; arq: variável do 4po FILE. Atenção! Você só pode ler de um arquivo que já exista! 267
Leitura de arquivo binário Exemplo: Ler os elementos de uma matriz 2 3 de inteiros a par4r do arquivo matriz.bin. matriz.bin int int int int int int FILE *in; int a[2][3]; in = fopen("matriz.bin", "rb"); fread(&a, sizeof(int), 6, in); fclose(in); // ler 6 registros de tamanho inteiro O armazenamento dos registros na matriz a é feito por linhas. 268 Escrita em arquivo binário A função fwrite() é u4lizada para a escrita de registros em um arquivo binário. Sua sintaxe é: fwrite(&var, numbytes, cont, arq); &var: o endereço da variável onde o registro está armazenado; numbytes: tamanho do registro a ser escrito (em bytes); cont: numero de registros a serem escritos; arq: variável do 4po FILE. 269
Escrita em arquivo binário Exemplo: Escrever para arquivo binário as informações dos 50 clientes de um banco, que estão armazenados na seguinte estrutura: typedef struct char nome[120]; int conta; char dv; double saldo; cliente; FILE *out; cliente c[50]; int i; out = fopen("clientes.bin", "wb"); for (i = 0; i < 50; i++) // escrever 1 registro por vez fwrite(&c[i], sizeof(cliente), 1, out); fclose(out); 270 Escrita em arquivos binários Na estrutura do exemplo anterior: typedef struct char nome[120]; // 120 bytes int conta; // 4 bytes char dv; // 1 byte double saldo; // 8 bytes cliente; cada registro será composto por 133 bytes. A informação de cada cliente será armazenada de acordo com a seguinte representação: nome conta dv saldo O arquivo será interpretado como uma seqüência de registros: 133 bytes c[i] c[0] c[1] c[2] c[49] 271
Rebobinando um arquivo A função rewind() da biblioteca stdio.h reposiciona o ponteiro de posição no início de um arquivo aberto em modos de acesso específicos. int peso; float altura; arq = fopen("cadastro.dat", "w+"); // abrir para escrita e leitura do printf("informe o peso e a altura da pessoa: "); scanf("%d %f", &peso, &altura); fprintf(arq, "%3d %.2f\n", peso, altura); while ( peso!= -1 ); rewind(arq); while (!feof(arq) ) fscanf(arq, "%d %f", &peso, &altura); printf("%3d %.2f\n", peso, altura); fclose(arq); 272 Pesquisa em arquivos Ao abrir um arquivo, o ponteiro de posição estará no início do arquivo. A cada dado lido ou gravado, este ponteiro desloca-se para frente. A função fseek() é u4lizada para posicionar o ponteiro de um arquivo em uma determinada posição de um arquivo. Sua sintaxe é: fseek(arq, deslocamento, origem) arq: variável do 4po FILE; deslocamento: quan4dade, em bytes, a ser avançada (posi4vo) ou recuada (nega4vo). origem: SEEK_SET = início do arquivo. SEEK_CUR = posição atual. SEEK_END = fim do arquivo. 273
Pesquisa em arquivos Exemplo: Subs4tuir por 0 todos os valores nega4vos de um arquivo texto. FILE *in; float valor; in = fopen("dados.txt", "r+"); // abrir para leitura e escrita while (!feof(in) ) fscanf(in, "%f", &valor); if ( valor < 0.0 ) fseek(in, -sizeof(float), SEEK_CUR); // voltar 1 float fprintf(in, "%f", 0); fclose(in); 274 275