You are on page 1of 22

Arquivo em C

Parte 2: Arquivos modo binrio

Naur jr. IFSP-HTO PLP2- 2sem 2014

Contedo
Introduo
Dificuldade de atualizao em arquivos texto
Vantagens com arquivo binrio

Manipulando arquivos binrios

Abrindo
Modo de abertura de arquivo binrio
Escrevendo/Lendo
Posicionando em arquivo binrio
Fechando

Exemplo Conta Corrente

Introduo

Fim de
arquivo EOF

Analogia de arquivo modo texto: fita continua...


1 jose 10.00 2 maria 23.00 3 cristina 23.00 .....

Dificuldade de atualizao em arquivos texto


O que aconteceria se alterar o saldo de jose de 10.00 para 1,000.23?
1 jose 1,000.00 maria 23.00 3 cristina 23.00 .....

O que aconteceria se alterar o nome de maria para marina?


1 jose 10.00 2 mariana3.00 3 cristina 23.00 .....

Quando perceber que haver necessidade de atualizao


Arquivo Binrio

Introduo
unsigned int conta;
char nome[ 30 ];
double saldo;

1 jose 10.00 2 maria 23.00 3 cristina 23.00 .....


1 joseane 103.00 2 mariana 23.00 3 cristina 230.00 .....

Quando armazenamos modo texto:


cada campo pode variar de tamanho.

Arquivo modo binrio:


0

100

200

Vago cada um com 100 bytes


300

400

Vantagens na manipulao com arquivo binrio


Randmico (rapidez)
Facilidade na alterao (inserir dados ou alterar sem destruio.

struct Conta {
unsigned int conta // bytes?
char nome[ 30 ]
// bytes?
double saldo;
// bytes?
}
Sempre o mesmo tamanho!!!

Manipulando arquivos binrios


1 Abertura de Arquivo:
fopen(Arquivo, MODO): funo que abre o arquivo.
FILE fopen( const char *nome_arquivo, const char *modo_abertura );
fptr = fopen(cliente.dat","wb");
fptr = fopen(" cliente.dat",rb");

// Abertura do arquivo binrio para escrita


// Abertura do arquivo binrio para leitura

O valor de retorno da funo fopen() muito importante! Ele o identificador do fluxo que voc abriu e
s com ele que voc conseguir ler e escrever no arquivo aberto.
Se houver um erro na abertura/criao do arquivo, a funo retornar o valor NULL. O erro geralmente
acontece por duas razes:
O arquivo no existe, caso tenha sido requisitado para leitura.
O usurio atual no tem permisso para abrir o arquivo com o modo de acesso pedido. Por exemplo, o
arquivo somente-leitura, ou est bloqueado para gravao por outro programa, ou pertence a outro
usurio e no tem permisso para ser lido por outros.

Manipulando arquivos binrios


Modo

Significado

Abre o arquivo somente para leitura. O arquivo deve existir. (O r vem do ingls read, ler)

r+

Abre o arquivo para leitura e escrita. O arquivo deve existir.

Abre o arquivo somente para escrita no incio do arquivo. Apagar o contedo do arquivo se ele j
existir, criar um arquivo novo se no existir. (O w vem do ingls write, escrever)

w+

Abre o arquivo para escrita e leitura, apagando o contedo pr-existente.

Abre o arquivo para escrita no final do arquivo. No apaga o contedo pr-existente. (O a vem do
ingls append, adicionar, apender)

a+

Abre o arquivo para escrita no final do arquivo e leitura.

Em ambientes DOS/Windows, ao ler arquivos binrios (por exemplo, programas


executveis ou certos tipos de arquivos de dados), deve-se adicionar o caractere "b" ao
final da string de modo (por exemplo, "wb" ou "r+b") para que o arquivo seja
lido/gravado corretamente.
Isso necessrio porque no modo texto (o padro quando no adicionado o b) ocorrem
algumas tradues de caracteres (por exemplo, a terminao de linha "\r\n" substituda
apenas por "\n" na leitura) que poderiam afetar a leitura/gravao dos arquivos binrios
(indevidamente inserindo ou suprimindo caracteres).

;)pf* ELIF,tnuoc tni,setyb_ed_oremun tni,reffub* diov(etirwf dengisnu

ETAPAS: Abertura, Manipulao e Fechamento


2 Manipulao de Arquivo (leitura/escrita):
Escrita:

fwrite (&VARIVEL,TAMANHO,QUANTIDADE,ARQUIVO);
- Escreve no arquivo a varivel.
- Recebe quatro argumentos: o endereo da varivel, o tamanho em byte da varivel, a quantidade de registros e o
ponteiro para a estrutura FILE do arquivo.
- Retorna o nmero de itens escritos.

int fwrite (void *buffer,int numero_de_bytes,int count,FILE *fp);

fwrite( &cdigo, sizeof(int) , 1, fptr);

struct clienteConta {
unsigned int contaNum;
char nome[ 25 ];
double saldo;
};
struct clienteConta vazioCliente;

fwrite( &vazioCliente, sizeof( struct clienteConta ), 1, cfPtr );

ETAPAS: Abertura, Manipulao e Fechamento


2 Manipulao de Arquivo (leitura/escrita):
Leitura:
fread (VARIVEL,TAMANHO,QUANTIDADE,ARQUIVO); ):
- L os dados do arquivo para a varivel.
- Recebe quatro argumentos: o endereo da varivel, o tamanho em byte a ser lido, , a
quantidade de registros, e o ponteiro para a estrutura FILE do arquivo.
- Retorna o nmero de itens lidos. Esse valor poder ser menor que QUANTIDADE se
o final do arquivo for atingido ou ocorrer um erro.
int fread (void *buffer, int numero_de_bytes, int num_elemt, FILE *fp);
Ex:

fread(&codigo,sizeof(codigo),1, fptr);
fread( &cliente, sizeof( struct clienteConta ), 1, cfPtr );

ETAPAS: Abertura, Manipulao e Fechamento


3 Fechamento:
fclose (ARQUIVO):
- Fecha o arquivo e esvazia o contedo do buffer, garantindo que nenhuma
informao seja deixado no buffer, tambm chamado de descarga ou flushing
- Libera as reas de comunicao entre o programa e sistema operacional.
int fclose( FILE *ponteiro_arquivo);
Ex: fclose(fptr)

Escrevendo/Lendo Aleatoriamente (posio)


movendo pelo arquivo
Para apontar para um byte especfico dentro do arquivo movimenta o indicador de posio. Isto pode ser feito
com o uso da funo fseek( ),cuja sintaxe :
fseek(ARQUIVO, NMERO_DE_BYTES, ORIGEM);
Onde:

ARQUIVO um ponteiro de arquivo aberto anteriormente,


NMERO_DE_BYTES a quantidade de bytes que o indicador de posio ser movimentado e
ORIGEM a partir de onde o movimento do indicador de posio iniciar.

ORIGEM deve ser uma das seguintes macros:


SEEK_SET 0 Incio do arquivo
SEEK_CUR 1 Ponto corrente no arquivo

100

200

300

SEEK_END 2 Fim do arquivo

fseek( fPtr, ( conta - 1 ) * sizeof( struct clienteConta ), SEEK_SET );

400

Apontando para o incio do arquivo (voltar


para o incio)
Para apontar para o incio do arquivo use a funo rewind( )
rewind(ARQUIVO);
- sendo ARQUIVO um ponteiro de arquivo.
Outras funes:
remove(ARQUIVO); //remove arquivo
rename(ARQUIVO_ANTIGO, ARQUIVO_NOVO);
flush(ARQUIVO); //esvaziar o contedo de um stream

Criando e ZERANDO Arquivo:


1.
2.
3.
4.
5.

struct ClienteConta {
int numConta;
char nome[ 45 ];
double saldo;
};

6.
7.
8.

int main( void ){

// numero da conta
// nome
// saldo

int i; // contador usado para conta de 1-100

9.
10.
11.

struct ClienteConta clienteVazio = { 0, "", 0.0 }; // // cria ClienteConta com informao default

12.
13.
14.
15.
16.
17.
18.
19.
20.
21.

if ( (cArquivoPtr = fopen( "contas.dat", "wb" ) ) == NULL ) //abre arquivo para escrita se existe descarta contedo
puts( "Arquvio nao pode ser aberto." );
else {

22.

FILE *cArquivoPtr; // ponteiro para arquivo contas.dat

for ( i = 1; i <= 100; ++i )


// gera 100 registros em branco para o arquivo
fwrite( &clienteVazio, sizeof( struct ClienteConta ), 1, cArquivoPtr );
fclose (cArquivoPtr; ); // fclose fecha arquivo
} // fim else
} // fim main

1.
2.
3.
4.
5.

struct ClienteConta {
int numConta;
char nome[ 45 ];
double saldo;
};

6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.

Escrevendo apenas 1 estrutura no


Arquivo

int main( void ){

20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.

// numero da conta
// nome
// saldo

FILE *cArquivoPtr;
struct ClienteConta cliente;
int numeroConta;
if ( (cArquivoPtr = fopen( "contas.dat", r+b" ) ) == NULL ) // abre arquivo para escrita se existe descarta contedo
puts( "Arquvio nao pode ser aberto." );
else {
printf( "%s", "Entre numero da conta ( 1 a 100):\n? " );
scanf( "%d", &numeroConta );
fflush(stdin);
//limpa o buffer de entrada do carater enter
fseek( cArquivoPtr, ( numeroConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET );
fread( & cliente, sizeof( struct ClienteConta ), 1, cArquivoPtr );
if ( cliente.numConta != 0 )
printf("A conta de numero: %d ja existe", numeroConta );
else{
printf( "%s", "Entre nome:\n? " );
gets(cliente.nome);
printf( "%s", "\nEntre com o saldo:\n? " );
scanf("%lf",&cliente.saldo);
cliente.numConta = numeroConta;
fseek( cArquivoPtr, ( cliente.numConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET ); // seta posicao para registro especifico
fwrite( &cliente, sizeof( struct ClienteConta ), 1, cArquivoPtr );
}
fclose( cArquivoPtr );
} // fim else
} // fim main

//escreve a estrutura com o dados para a posio no arquivo

1.
2.
3.
4.
5.

struct clienteConta {
int contaNum;
char nome[ 45 ];
double saldo;
};

6.
7.
8.
9.

Lendo estrutura do Arquivo


randomicamente p/ Tela

int main( void ){

10.
11.
12.
13.
14.

// numero da conta
// nome
// saldo

Este programa
seria qual
consulta em SQL?

FILE *cArquivoPtr;
struct ClienteConta cliente;
if ( (cArquivoPtr = fopen( "contas.dat", "rb" ) ) == NULL ) {
puts( "Arquivo nao pode ser aberto." );
}
else {
printf( "%-6s%-27s%10s\n", "Conta", "Nome", "Saldo" );

//cabecalho

15.

while ( !feof ( cArquivoPtr ) ) { // le todos registros do arquvivo ate eof

16.

fread( &cliente, sizeof ( struct ClienteConta ), 1, cArquivoPtr );

17.
18.
19.
20.

if ( cliente.numConta != 0 )
printf( "%-6d%-27s%10.2f\n", cliente.numConta, cliente.nome, cliente.saldo );

21.
22.
23.

}
fclose( cArquivoPtr ); // fclose fecha arquivo
} // fim else
} // fim main

1.
2.
3.
4.
5.

struct clienteConta {
int contaNum;
char nome[ 45 ];
double saldo;
};

6.
7.
8.

Lendo estrutura do Arquivo


randomicamente e escrevendo
modo texto.

int main( void ){

9.
10.

11.
12.
13.
14.
15.
16.
17.
18.
19.

// numero da conta
// nome
// saldo

FILE *cArquivoPtr; // leitura


FILE *cEscritaPtr; // escrita modo texto
struct ClienteConta cliente;
if ( (cArquivoPtr = fopen( "contas.dat", "rb" ) ) == NULL ) {
puts( "Arquivo nao pode ser aberto." );
return;
}
if ( (cArquivoPtr = fopen( "contas.txt", w" ) ) == NULL )
puts( "Arquivo nao pode ser aberto." );
else {
fprintf(*cEscritaPtr, "%-6s%-27s%10s\n", "Conta", "Nome", "Saldo" );

//cabecalho

20.

while ( !feof ( cArquivoPtr ) ) { // le todos registros do arquvivo ate eof

21.

fread( &cliente, sizeof ( struct ClienteConta ), 1, cArquivoPtr );

22.
23.

if ( cliente.numConta != 0 )
fprintf(escritaPtr, "%-6d%-27s%10.2f\n", cliente.numConta, cliente.nome, cliente.saldo );

24.
25.
26.
27.
28.

}
fclose( cArquivoPtr ); // fclose fecha arquivo
} // fim else
return 0;
} // fim main

1.
2.
3.
4.
5.

struct clienteConta {
int numConta;
char nome[ 45 ];
double saldo;
};

6.
7.
8.
9.
10.

Removendo estrutura do
Arquivo randomicamente

int main( void ){

// numero da conta
// nome
// saldo

FILE *cArquivoPtr; // leitura


struct ClienteConta cliente;
struct ClienteConta clienteVazio = { 0, , 0.00) ; //til para escrever no lugar do removido

11.
12.
13.
14.
15.
16.
17.
18.
19.
20.

if ( (cArquivoPtr = fopen( "contas.dat", "r+b" ) ) == NULL ) {


puts( "Arquivo nao pode ser aberto." );
return;
}

21.
22.
23.
24.
25.

if ( cliente.numConta == 0 )
printf("A conta de numero: %d esta VAZIA", numeroConta );
else{
printf("Dados da conta a ser removida \n");
printf( "%-6d%-27s%10.2f\n", cliente.numConta, cliente.nome, cliente.saldo );

26.
27.
28.
29.
30.
31.
32.

printf( "%s", "Entre numero da conta para ser removida ( 1 a 100):\n? " );
scanf( "%d", &numeroConta );
fseek( cArquivoPtr, ( numeroConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET );
fread( &cliente, sizeof( struct ClienteConta ), 1, cArquivoPtr );

fseek( cArquivoPtr, ( numeroConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET );


fwrite( &clienteVazio, sizeof( struct ClienteConta ), 1, cArquivoPtr );
printf("remove conta com sucesso!!!" );
}
fclose( cArquivoPtr ); // fclose fecha arquivo
return 0;
} // fim main

1.
2.
3.
4.
5.

struct clienteConta {
int numConta;
char nome[ 45 ];
double saldo;
};

6.
7.
8.
9.
10.
11.

Atualizando saldo: deposito e


saque em arquivo

int main( void ){

// numero da conta
// nome
// saldo

FILE *cArquivoPtr;
// leitura
struct ClienteConta cliente;
int numConta;
double transacao;
//valor do saque ou deposito

12.
13.
14.
15.
16.
17.
18.
19.
20.
21.

if ( (cArquivoPtr = fopen( "contas.dat", "r+b" ) ) == NULL ) {


puts( "Arquivo nao pode ser aberto." );
return 0;
}

22.
23.
24.
25.
26.
27.
28.

if ( cliente.numConta == 0 )
printf("A conta de numero: %d esta VAZIA", numConta );
else{
printf( "%-6d%-27s%10.2f\n", cliente.numConta, cliente.nome, cliente.saldo );
printf( "%s", "Entre deposito ( + ) or saque ( - ): " );
scanf( "%lf", &transacao );
cliente.saldo += transacao; // atualiza saldo do registro

29.
30.
31.
32.
33.

printf( "%s", "Entre numero da conta para ser removida ( 1 a 100):\n? " );
scanf( "%d", &numeroConta );
fseek( cArquivoPtr, ( numeroConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET );
fread( &cliente, sizeof( struct ClienteConta ), 1, cArquivoPtr );

fseek( cArquivoPtr, ( numeroConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET );


fwrite( &clienteVazio, sizeof( struct ClienteConta ), 1, cArquivoPtr );
}
fclose( cArquivoPtr ); // fclose fecha arquivo
return 0;
} // fim main

1.
2.
3.
4.
5.

struct clienteConta {
int numConta;
char nome[ 45 ];
double saldo;
};

6.
7.
8.
9.
10.
11.

int main( void ){

// numero da conta
// nome
// saldo

Atualizando nome da conta


em arquivo

FILE *cArquivoPtr;
// leitura
struct ClienteConta cliente;
int numConta;
char nome[]45];
//valor do saque ou deposito

12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.

if ( (cArquivoPtr = fopen( "contas.dat", "r+b" ) ) == NULL ) {


puts( "Arquivo nao pode ser aberto." );
return 0;
}

23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.

if ( cliente.numConta == 0 )
printf("A conta de numero: %d esta VAZIA", numConta );
else{
printf( "%-6d%-27s%10.2f\n", cliente.numConta, cliente.nome, cliente.saldo );
printf( "%s", "Entre nome: " );
gets( nome );

35.
36.
37.

printf( "%s", "Entre numero da conta para ser removida ( 1 a 100):\n? " );
scanf( "%d", &numeroConta );
fflush(stdin);
fseek( cArquivoPtr, ( numeroConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET );
fread( &cliente, sizeof( struct ClienteConta ), 1, cArquivoPtr );

strcpy(cliente.nome, nome);

// atualiza nome do registro

printf( "%-6d%-27s%10.2f\n", cliente.numConta, cliente.nome, cliente.saldo );


fseek( cArquivoPtr, ( numeroConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET );
fwrite( &clienteVazio, sizeof( struct ClienteConta ), 1, cArquivoPtr );
}
fclose( cArquivoPtr ); // fclose fecha arquivo
return 0;
} // fim main

Referncias
Video Aulas (YouTube)
Programar em C - Manipulao de Arquivos txt em C / Ler Dados https://www.youtube.com/watch?v=y_euDUgoND8
Programar em C - Manipulao de Arquivos txt em C / Incluir Dados - Aula 84
https://www.youtube.com/watch?annotation_id=annotation_238568&feature=iv&src_vid=y_euDU
goND8&v=USsUSMpNGsM
Sites sobre manipulao de Arquivos em C
http://homepages.dcc.ufmg.br/~joaoreis/Site%20de%20tutoriais/c_int/arquivos.htm
http://pt.wikibooks.org/wiki/Programar_em_C/Entrada_e_sa%C3%ADda_em_arquivos
http://www.vivaolinux.com.br/artigo/Manipulando-arquivos-em-C-%28parte-1%29/?pagina=4
http://homepages.dcc.ufmg.br/~joaoreis/Site%20de%20tutoriais/c_int/arquivos.htm
http://pt.wikibooks.org/wiki/Programar_em_C/Entrada_e_sa%C3%ADda_em_arquivos
http://www.ime.usp.br/~elo/IntroducaoComputacao/Manipulacao%20de%20arquivo.htm

Outros.. curiosidades
Streams padro
Quando um programa em linguagem C iniciado so abertas trs streams: stdin, stdout e stderr.
stdin define a entrada padro do sistema, normalmente o teclado.
stdout define a sada padro do sistema, normalmente o monitor.
stderr define a sada padro dos erros, normalmente tambm o monitor.

Estas streams so ponteiros de arquivos e podem ser redirecionadas. Assim, nas funes que voc utiliza
ponteiros de arquivos para entrada e sada de dados voc pode muito bem usar estas streams de modo ao seu
programa receber dados do teclado e escrever no monitor. Isto foi mostrado no exemplo da seo anterior na
linha;
fscanf(stdin,"%s",string); /* l string do teclado */
onde o programa leu a varivel string do teclado atravs da streams padro stdin.
Porm esteja consciente que estas streams no so variveis e no podem receber um valor. Ou seja, voc
no pode abr-las com fopen.
Quando o programa encerrado estas streams so fechadas automaticamente, do mesmo jeito que foram
criadas, voc no deve nunca tentar abr-las ou fech-las.

Variaes dos exemplos


Escreve vrias contas at que usurio digite 0
escrevecontaMult.c

RemoveConta confirmando remoo com usurio.


removeConta.c

1.
2.
3.
4.
5.

struct ClienteConta {
int numConta;
char nome[ 45 ];
double saldo;
};

6.
7.
8.
9.
10.

Escrevendo estrutura no Arquivo


randomicamente

int main( void ){

11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.

// numero da conta
// nome
// saldo

FILE *cArquivoPtr;
struct ClienteConta cliente;
if ( (cArquivoPtr = fopen( "contas.dat", r+b" ) ) == NULL ) // abre arquivo para escrita se existe descarta contedo
puts( "Arquvio nao pode ser aberto." );
else {
printf( "%s", "Entre numero da conta ( 1 a 100, 0 para finalizar )\n? " );
scanf( "%d", &cliente.numConta );
fflush(stdin);
//limpa o buffer de entrada do carater enter
while ( cliente.contaNum != 0 ) {
printf( "%s", "Entre nome:\n? " );
gets(cliente.nome);
printf( "%s", "\nEntre com o saldo:\n? " );
scanf("%lf",&cliente.saldo);
fseek( cArquivoPtr, ( cliente.numConta - 1 ) * sizeof( struct ClienteConta ), SEEK_SET ); // seta posicao para registro especifico

25.

fwrite( &cliente, sizeof( struct ClienteConta ), 1, cArquivoPtr );

26.
27.
28.

printf( "%s", "Entre com numero da conta:\n? " );


scanf( "%d", &cliente.numConta );
fflush(stdin);

29.
30.
31.
32.

}
fclose( cArquivoPtr );
} // fim else
} // fim main

//escreve a estrutura com o dados para a posio no arquivo

//limpa o buffer de entrada do carater enter

You might also like