Você está na página 1de 27

Arquivos binários

continuação

1
1 INF 01202 - Prof. Marcelo Walter – Aula 25
Leitura/Gravação em arquivos

•  A leitura ou gravação de um stream de/para o arquivo


causa um deslocamento da posição corrente do arquivo, em
relação ao momento anterior à operação de entrada ou
saída de dados.
•  A posição corrente (correspondente à posição do início da
operação) é deslocada pela adição do número de bytes lidos
ou gravados, ou seja, a nova posição corrente fica sendo o
byte imediatamente seguinte ao último processado (leitura
ou gravação).

Posição corrente Posição corrente


Bytes lidos
ou gravados
Após operação:
Nova
Posição corrente
2 INF 01202 - Prof. Marcelo Walter – Aula 25
Mais funções de manipulação de arquivo

•  rewind (visto aula passada)


•  fseek
•  ftell

3 INF 01202 - Prof. Marcelo Walter – Aula 25


Funções de manipulação de arquivos
Pode ser
fseek(point_arq,numbytesdesloc,origem) negativo…
Move a posição corrente de leitura/escrita para a posição
calculada origem + numbytesdesloc.
Os valores possíveis, definidos, para origem do deslocamento
são:
SEEK_SET ou 0 = início do arquivo
SEEK_CUR ou 1 = ponto corrente no arquivo
SEEK_END ou 2 = fim do arquivo
-> Usar apenas quando quiser alterar o acesso sequencial ao
arquivo, que ocorre quando do uso consecutivo de funções
de leitura ou gravação de arquivo!
...
FILE *arq;
struct estrutura buffer;
arq = fopen(...);
/*coloca a posição para o início na 2a estrutura do arquivo*/
fseek(arq, sizeof(struct estrutura),SEEK_SET);
fread(&buffer,...,...,arq);// lê 2o registro
...
...

ATENÇÃO: fseek SÓ POSICIONA. NÃO LÊ, NEM GRAVA !


4 INF 01202 - Prof. Marcelo Walter – Aula 25
Funções de manipulação de arquivos

ftell(point_arq)

Indica a posição corrente no arquivo.


-> Posição dada em bytes.

...
FILE *arq;
arq = fopen(...);
...

/*posição corrente = início*/


printf("\nposicao atual em bytes antes leitura%d\n", ftell(arq));
if (fread(&buffer,sizeof(TIPO_ATLETA), 1, arq) == 1)
//lê, confirma se o que foi lido conteúdo e não EOF, então imprime:
printf("\nposicao atual em bytes apos leitura%d\n", ftell(arq));
...
...

5 INF 01202 - Prof. Marcelo Walter – Aula 25


Arquivos binários
acesso randômico

6 INF 01202 - Prof. Marcelo Walter – Aula 25


Acesso Randômico

•  Acesso a pontos de um arquivo, sem percorrer


sequencialmente o conteúdo que antecede o
conteúdo desejado.
•  Motivações:
•  a posição desejada de leitura ou escrita pode não
ser coincidente com a posição corrente do arquivo
válida em um certo momento.
•  A posição corrente de leitura ou escrita pode ser
alterada para qualquer posição do arquivo.

7 INF 01202 - Prof. Marcelo Walter – Aula 25


Exercícios

Faça um programa para :


1.  Atualizar a idade de um determinado atleta, cujo nome
foi lido do teclado (lembre os exercícios da aula
anterior).

ü  Arquivo gerado de forma sequencial: posição onde se


encontram os dados do atleta pesquisado é desconhecida.
ü  O arquivo tem que ser lido sequencialmente, desde o início,
comparando-se o nome do atleta que se busca alterar com os
nomes dos atletas armazenados no arquivo, até localizar-se
a posição da alteração ou atingir o fim do arquivo.
ü  A posição corrente precisa ser alterada, para permitir que a
gravação se sobreponha ao conteúdo lido do arquivo.

8 INF 01202 - Prof. Marcelo Walter – Aula 25


Busca atleta e imprime idade (sem alterar arquivo ainda)
// Programa de manipulação de arquivos:
#include <stdio.h> // e demais biblioteca necessárias
#include <string.h>

typedef struct str_atleta


{ /*declaração da estrutura utilizada*/
char nome[31];
int idade;
float altura;
}TIPO_ATLETA;
...
int main( )
{
FILE *arq; //declaração de um“ponteiro de arquivo”
int encontrado = 0, op, contador= 0; // para deslocamento
TIPO_ATLETA buffer;
char procurado[31], nome[16]; // nome do atleta e nome do arquivo
printf("Nome do arquivo: ");
gets (nome);
if( (arq = fopen(nome,"r+b")) == NULL) // abertura para leitura e escrita
printf("Erro abertura");
else
{

9 INF 01202 - Prof. Marcelo Walter – Aula 25


Busca atleta e imprime idade (sem alterar arquivo ainda)
.....
do
{
printf("Nome do procurado: ");
fflush(stdin);
gets(procurado); // nome para pesquisa no arquivo
encontrado = 0; // habilita laço de busca
rewind(arq); // posiciona no início do arquivo, para iniciar busca
while(!feof(arq) && encontrado == 0) //pára qdo. acha ou fim do arquivo
if (fread(&buffer,sizeof(TIPO_ATLETA),1,arq) == 1) // testa leitura
if(!(strcmp(buffer.nome,procurado))) // se as strings forem iguais
{
printf("\nIdade cadastrada %d",buffer.idade);
encontrado = 1; //fica verdade e interrompe a busca
}
if (!encontrado) // mesmo que (encontrado == 0)
printf("\nAtleta nao foi localizado.");
printf("\n1-Procurar outro, 2-Encerrar\n");
do // lê e valida opção do usuário
{
scanf("%d", &op);
if (op<1 || op>2)
printf(“Opcao invalida! Informe novamente: “);
} while (op<1 || op > 2);
} while (op == 1);
fclose(arq);
}
return 0; 10
}
10 INF 01202 - Prof. Marcelo Walter – Aula 25
.....
do
{
printf("Nome do procurado: ");
fflush(stdin);
gets(procurado); // nome para pesquisa no arquivo
encontrado = 0; // habilita laço de busca
rewind(arq); // posiciona no início do arquivo, para iniciar busca
while(!feof(arq) && encontrado == 0) //pára qdo. acha ou fim do arquivo
if (fread(&buffer,sizeof(struct atleta),1,arq) == 1) // testa leitura
Atualiza campo e grava atualização
if(!(strcmp(buffer.nome,procurado))) // se as strings forem iguais
{
printf("\nIdade cadastrada %d",buffer.idade);
encontrado = 1; //fica verdade e interrompe a busca
}
if (!encontrado) // mesmo que (encontrado == 0)
printf("\nAtleta nao foi localizado.");
printf("\n1-Procurar outro, 2-Encerrar\n");
do
{
scanf("%d", &op);
if (op<1 || op>2)
printf(“Opcao invalida! Informe novamente: “);
} while (op<1 || op > 2);
} while (op == 1);
fclose(arq);
}
return 0;
} 11
11 INF 01202 - Prof. Marcelo Walter – Aula 25
Alteração da idade de atleta procurado – opção 1
// opção 1, deslocando do início do arquivo: (trecho correspondente à caixa
pontilhada)
...
while(!feof(arq) && encontrado == 0) //pára qdo. acha ou fim do arquivo
if (fread(&buffer,sizeof(TIPO_ATLETA),1,arq) == 1) // retornou 1
{
if(!(strcmp(buffer.nome,procurado))) // se as strings forem iguais
{
encontrado = 1; // encontrou
printf("\nIdade cadastrada %d",buffer.idade);
printf("\nInforme alteração da idade: ");
Próximo slide
scanf("%d",&buffer.idade);
//posiciona no lugar anterior à leitura, a partir do início do arquivo:
fseek(arq, contador * sizeof(TIPO_ATLETA),SEEK_SET);

//substitui, verificando se gravação foi bem sucedida


if(fwrite(&buffer,sizeof(TIPO_ATLETA),1,arq) != 1)
printf("\nErro de gravacao!!!\n”)
}
contador++; // contabiliza nro de elementos analisados - 1
}
....

12 INF 01202 - Prof. Marcelo Walter – Aula 25


Alteração da idade de atleta procurado – opção 2

// opção 2, retornando ao ponto do início da leitura: (trecho


correspondente à caixa pontilhada)
...
while(!feof(arq) && encontrado == 0) //pára qdo. acha ou fim do arquivo
if (fread(&buffer,sizeof(TIPO_ATLETA),1,arq) == 1) // retornou 1
if(!(strcmp(buffer.nome, procurado))) // se strings iguais
{
encontrado = 1;
printf("\nIdade cadastrada %d",buffer.idade);
printf("\nInforme alteração da idade: ");
scanf("%d",&buffer.idade);
Próximo
//posiciona no lugar anterior slide
à leitura, usando deslocamento negativo
fseek(arq, -sizeof(TIPO_ATLETA),SEEK_CUR);
//substitui, verificando se gravação foi bem sucedida
if(fwrite(&buffer,sizeof(TIPO_ATLETA),1,arq) != 1)
printf("\nErro de gravacao!!!\n");

}
....
Obs.: veja que o
contador usado na
opção 1 não é
necessário

13 INF 01202 - Prof. Marcelo Walter – Aula 25


Alteração da idade de um atleta determinado, através de função:
/* Altera um arquivo com dados atletas. */
#include <stdio.h>
#include <string.h>
typedef struct str_atleta
{ char nome[31];
int idade;
float altura; }TIPO_ATLETA;
void AlteraIdade(FILE *); // protótipo da função
int main( )
{
FILE *arq;
TIPO_ATLETA buffer; // variável buffer para o arquivo
char nome_arquivo[15] =“atletas.bin"; // nome do arquivo
int op;
if(!(arq = fopen(nome_arquivo,"r+b"))) // permite leitura e gravação
printf("Erro abertura");
else
{ do {
AlteraIdade (arq);
printf("\n1-Procurar outro, 2-Encerrar\n");
do {
scanf("%d", &op);
if (op<1 || op>2)
printf(“Opcao invalida! Informe novamente: “);
} while (op<1 || op > 2);
} while (op == 1);
fclose(arq);
}
return 0;
14 } INF 01202 - Prof. Marcelo Walter – Aula 25
Alteração da idade de um atleta determinado, através de função:
void AlteraIdade(FILE *arq)
{ Varreduras sequenciais do
int encontrado = 0; arquivo: a cada varredura,
TIPO_ATLETA buffer; é verificado se um atleta
char procurado[31]; procurado foi encontrado.
printf("Nome do procurado: ");
fflush(stdin);
gets(procurado); // nome para pesquisa no arquivo
encontrado = 0; // habilita laço de busca
rewind(arq); // reposiciona no início do arquivo
while(!feof(arq) && encontrado == 0) //pára qdo. acha ou fim do arquivo
if (fread(&buffer,sizeof(TIPO_ATLETA),1,arq) == 1) // retornou 1
if(!(strcmp(buffer.nome,procurado))) // se as strings forem iguais
{
encontrado = 1; Aqui o
printf("\nIdade cadastrada %d",buffer.idade); posicionamento aos
printf("\nNova Idade: "); dados é randômico
scanf("%d",&buffer.idade);
//posiciona no ponto para substituir, usando deslocamento negativo
fseek(arq, -sizeof(TIPO_ATLETA),SEEK_CUR);
//substitui, verificando se gravação foi bem sucedida
if(fwrite(&buffer,sizeof(TIPO_ATLETA),1,arq) != 1)
printf("\nErro de gravacao!!!\n");
}
if (encontrado == 0)
printf(“\nNome não está cadastrado.”);
}
15 INF 01202 - Prof. Marcelo Walter – Aula 25
Exercícios

Faça um programa que :


1.  Crie um arquivo de atletas de forma randômica, onde o
código do atleta indica a posição do seu registro no
arquivo. Use o mesmo tipo struct definido no exercício
anterior.

16 INF 01202 - Prof. Marcelo Walter – Aula 25


Criação randômica do arquivo com dados de atletas: código

/*
Cria um arquivo com dados de uma estrutura
com informações de atletas, de forma randômica.
*/
#include <stdio.h>
#include <string.h>
#define MAXCOD 10 // codigos dos atletas entre 1 e 10
#define MAXNOME 16 // tamanho do nome do arquivo

typedef struct atleta


{
char nome[31];
int idade;
float altura;
}TIPO_ATLETA;

void listaarquivo(FILE*);

17 INF 01202 - Prof. Marcelo Walter – Aula 25


Criação randômica do arquivo com dados de atletas: código

int main ( )
{
FILE *arq;
int encontrado = 0, op, cod;
char nome[MAXNOME], procurado[30];
TIPO_ATLETA buffer;
printf("Nome do arquivo: ");
gets(nome);
if(!(arq = fopen(nome,"w+b"))) //cria ou recria
printf("Erro criacao");
else
{
do
{
/* TRECHO DE CRIAÇÃO DO ARQUIVO NO SLIDE A SEGUIR*/
} while (op != 2);

listaarquivo(arq);
fclose(arq);
}
return 0;
}
18
18 INF 01202 - Prof. Marcelo Walter – Aula 25
Criação randômica do arquivo com dados de atletas: código
...
do
{ //coleta dados do usuário e os escreve
do
{ // lê código do atleta, consistindo:
printf("Codigo do atleta, entre 1 e %d: “, MAXCOD);
scanf("%d", &cod);
if (cod < 1 || cod > MAXCOD)
printf("\nCodigo deve estar entre 1 e %d!\n", MAXCOD);
} while (cod < 1 || cod > MAXCOD);
cod = cod - 1; // corrige para o índice de deslocamento no arquivo
printf("Nome: ");
fflush(stdin);
gets(buffer.nome); // lê nome
printf("Idade: ");
scanf("%d",&buffer.idade);
printf("Altura: ");
scanf("%f",&buffer.altura);
fseek(arq,cod*sizeof(TIPO_ATLETA),SEEK_SET);
fwrite(&buffer,sizeof(TIPO_ATLETA),1,arq);
fflush(arq); // força a gravação física (opcional, a gravaçao seria feita no fclose)
printf("\n1-InserirNovo, 2-Encerrar: ");
scanf("%d", &op);
} while(op != 2);
....
19
19 INF 01202 - Prof. Marcelo Walter – Aula 25
Criação randômica do arquivo com dados de atletas: exemplo de execução

20 INF 01202 - Prof. Marcelo Walter – Aula 25


Listagem sequencial de cadastro gerado de forma
randômica, mostrando registros vazios:
void listaarquivo(FILE *arq)
{
TIPO_ATLETA buffer;
rewind(arq);
printf("-----Comeco da listagem-----\n");
while(!feof(arq)) // enquanto não chegou no final
/*testa leitura, para não considerar a tentativa final, que lê EOF*/
if(fread(&buffer,sizeof(TIPO_ATLETA),1,arq) == 1)
{ //para que detecção de final do arquivo não cause impressão:
printf("Nome: %s\n",buffer.nome);
printf("Idade: %d\n",buffer.idade);
printf("Altura: %.2f\n\n",buffer.altura);
}
printf("-----Fim da listagem-----\n");
}

21 INF 01202 - Prof. Marcelo Walter – Aula 25


Listagem de cadastro
1 gerado de forma
randômica : execução

Bytes associados a
campos não lidos são
gravados como
5 00000000 (binário).

Corresponde ao
caracter ‘\0’ quando
o byte é lido como um
char.

10
22 INF 01202 - Prof. Marcelo Walter – Aula 25
Listagem sequencial de cadastro gerado de forma randômica, mostrando
apenas registros preenchidos e código do atleta (associado à posição):

void listaarquivo_1(FILE *arq)


{
TIPO_ATLETA buffer;
int cod_atl = 1; //para informar o código do atleta
rewind(arq);
printf("-----Comeco da listagem-----\n");
while(!feof(arq)) // enquanto não chegou no final
/*testa leitura, para não considerar a tentativa no final*/
if(fread(&buffer,sizeof(TIPO_ATLETA),1,arq) == 1)
{ //para que detecção de final do arquivo não cause impressão:
if ( buffer.idade > 0) // para não imprimir registros vazios...
{
printf("Codigo: %i\n",cod_atl);
printf("Nome: %s\n",buffer.nome);
printf("Idade: %d\n",buffer.idade);
printf("Altura: %.2f\n\n",buffer.altura);
}
cod_atl++; // soma sempre que lê
}
printf("-----Fim da listagem-----\n");
}

23 INF 01202 - Prof. Marcelo Walter – Aula 25


Listagem de cadastro randômico, sem registros vazios: execução

24 INF 01202 - Prof. Marcelo Walter – Aula 25


Exercício
Escreva um programa em C para ajudar com estatísticas de votações.
Um arquivo binário candidatos.bin contém um número indeterminado
de entradas do tipo TIPO_CANDIDATO, dado abaixo. Escreva um
programa que leia o arquivo binário e escreve na tela as seguintes
informações:
•  número de candidatos de cada partido;
•  o nome e o partido do candidato mais votado
•  o total de votos de cada partido (considerando que apenas 3
partidos existem a saber: A, B, C).

typedef struct str_candidato{


char nome[30];
char partido; // Um de: A,B,C
int nro_votos;
} TIPO_CANDIDATO;

25 INF 01202 - Prof. Marcelo Walter – Aula 25


#include <stdio.h>
#include <string.h>

typedef struct str_candidato {


char nome[30];
char partido;
int nro_votos;
} TIPO_CANDIDATO;

// Programa principal

int main(){

FILE *fpbin;
TIPO_CANDIDATO c;
int na=0, nb=0, nc=0;
int va=0, vb=0, vc=0;
int maior_votos=-1;
char nome_mais_votado[30];
char partido_mais_votado;

// segue no proximo slide

26 INF 01202 - Prof. Marcelo Walter – Aula 25


fpbin=fopen("candidatos.bin", "rb");

if (fpbin!=NULL){
while(!feof(fpbin)){
if (fread(&c,sizeof(TIPO_CANDIDATO),1,fpbin) == 1){
// encontra candidato mais votado
if (c.nro_votos > maior_votos){
strcpy(nome_mais_votado, c.nome);
partido_mais_votado = c.partido;
maior_votos = c.nro_votos;
}
switch(c.partido){
case 'A': na++; va += c.nro_votos; break;
case 'B': nb++; vb += c.nro_votos; break;
case 'C': nc++; vc += c.nro_votos; break;
}
}
printf("Candidato mais votado: %s do partido %c\n", nome_mais_votado,
partido_mais_votado);
printf("Numero de candidatos:\n Partido A %d\n Partido B %d\n Partido C %d\n”,
na,nb, nc);
printf("Totais de votos:\n Partido A %d\n Partido B %d\n Partido C %d\n", va,vb, vc);

fclose(fpbin);
}
else printf("Problema para abertura do arquivo binario!\n");
return
27 0; INF 01202 - Prof. Marcelo Walter – Aula 25
}

Você também pode gostar