Sei sulla pagina 1di 57

Estruturas de Dados

II
Arquivos

Prof. Dr. Fabio Rodrigues de la Rocha

(Arquivos)

1 / 57

Arquivos - Introdu
c
ao
Tipos de Arquivos
Podemos dividir os arquivos em 2 tipos: Arquivos Texto
e arquivos bin
arios.
Arquivos Texto sao arquivos que nao possuem um
formato definido, sendo composto apenas por
sequencias de bytes. Podemos ler e escrever
sequencias de bytes em arquivos de forma
semelhante a ler strings do teclado e escrever
strings na tela. Caso seja armazenado um valor
ex: 1234567 esse numero gastara 7 bytes pois
cada um de seus dgitos e representado como
um caractere. No windows um arquivo texto
(Arquivos) possue um caractere marcador de fim de
2 / 57

Arquivos - Introdu
c
ao
Tipos de Arquivos - continua
ca
o
Arquivos bin
arios sao arquivos que possuem uma
estrutura definida atraves de um typedef ou
struct e podemos ler ou gravar elementos com
estas estruturas. Podemos tambem gravar o
valor de variaveis int, float, double, etc. Caso
seja armazenado o valor de numero inteiro
1234567 esse numero (que e um inteiro de 32
bits) gastara 4 bytes de espaco pois um inteiro
ocupa 4 bytes.
(Arquivos)

3 / 57

Arquivos - Formas de acesso


Arquivos podem ser acessos de 3 formas:
a forma mais simples, a leitura e gravacao
Sequencial E
de dados ocorre de forma contnua em posicoes
sequenciais (isto e, uma apos a outra).
Direto Na forma de acesso direto, pode-se acessar
uma posicao n de um arquivo sem acessar as
posicoes anteriores.
Indexado Utiliza a forma de acesso direto para criar um
arquivo auxiliar de ndices. Este arquivo de
ndices sera utilizado para faciliar o acesso ao
arquivo direto.
(Arquivos)

4 / 57

Vis
ao dos arquivos

(Arquivos)

5 / 57

Vis
ao dos arquivos
A linguagem C promove suporte `a utilizacao de
arquivos por meio da biblioteca stdio.h;
Esta biblioteca fornece varias funcoes para
manipulacao de arquivos;
Realizada atraves de um de dado ponteiro, chamado
FILE;
Uma variavel do tipo ponteiro FILE e capaz de
identificar um arquivo no disco, direcionando para ele
todas as operacoes.

(Arquivos)

6 / 57

Cursor e um ponteiro que indica a partir de que


posicao, dentro do arquivo, uma operacao sera
executada;
Cada vez que uma operacao e realizada (por exemplo
a leitura de um dado), o ponteiro e deslocado para a
proxima posicao

(Arquivos)

7 / 57

Vis
ao dos arquivos
Essas variaveis sao declaradas como qualquer outro tipo
de ponteiro:
FILE *arq, *pont;
Na linguagem C, os dados podem ser gravados em
arquivos binarios ou de texto. Arquivos de texto podem
ser lidos diretamente. Arquivos binarios devem ser lidos
por programas especiais, que convertem a cadeia de bits
em informacoes compreensveis.

(Arquivos)

8 / 57

fopen ()
Abre um arquivo
fclose()
Fecha um arquivo
fputc() e fputs() Escreve um caractere e uma string no
arquivo
fgetc() e fgets() Le um caractere e uma string de um
arquivo
fseek()
Posiciona o arquivo em um byte especfico
para um arquivo o que printf() e para
fprintf()
E
o console
para um arquivo o que scanf() e para
fscanf()
E
o console

(Arquivos)

9 / 57

feof()

Verdadeiro se o fim de arquivo for encontrado


ferror()
Verdadeiro se ocorreu um erro
rewind() Recoloca o ponteiro de registro (indicador de posicao) no incio do arquivo
remove() Apaga um arquivo
fflush()
Descarrega um arquivo
fread()
Le sequencia de bytes de arquivo
fwrite() escreve sequencia de bytes em arquivo
ftell ()
Obtem a posicao atual no arquivo

(Arquivos)

10 / 57

fopen
Prototipo: FILE *fopen (char *nome do arquivo,char
*modo);
O primeiro parametro nome do arquivo: e o local
onde o arquivo se encontra ou se for criado, onde o
arquivo deve ser armazenado.
O segundo parametro modo: especifica como o
arquivo deve ser aberto.
r
Abre um arquivo apenas para leitura.
w Abrir um arquivo apenas para gravacao.
a
Adiciona dados ao final do arquivo
rb Abre um arquivo binario para leitura.
wb Cria um arquivo binario para escrita
ab Acrescenta dados binarios no fim do arquivo
(Arquivos)

11 / 57

fopen

Continuacao:
wb
Cria um arquivo binario onde poderao ser realizadas
ab
Anexa novos dados a uma arquivo binario
r+
Abre um arquivo de texto para leitura e escrita
w+ Cria um arquivo de texto para leitura e escrita
rb+ Abre um arquivo binario para leitura e escrita
wb+ Cria um arquivo binario para leitura e escrita

(Arquivos)

12 / 57

Exemplo:Abrindo e fechando
arquivos
1
2
3
4
5
6
7

8
9
10
11
12

#include <stdio.h>
main()
{
char *str1 = "/mnt/wind/teste/dbase/dbase";
FILE *fp; /* Declarao da estrutura */
fp=fopen (str1,"wb"); /* o arquivo se chama dbase
est localizado no diretrio /mnt/wind/teste/dbase
*/
if (!fp)
printf ("Erro na abertura do arquivo.");
else
printf("Arquivo aberto com sucesso.");
(Arquivos)

13 / 57

fopen

Quando a funcao fopen() e utilizada para abrir um


arquivo no modo escrita (w e wb), duas situacoes
podem ocorrer:
Se o arquivo nao existir, ele sera criado;
Se o arquivo ja existir, ele sera sobreposto por um novo
arquivo vazio.

(Arquivos)

14 / 57

fopen

Se a funcao fopen() for executada sem problemas, a


variavel arq recebera o endereco de memoria
ocupado pelo arquivo. Caso contrario recebera o
valor NULL. Desse modo e recomendavel testar o
retorno antes de manipular o arquivo.

(Arquivos)

15 / 57

fclose
A funcao fclose() fecha um arquivo. Quando ocorrer
algum erro durante a execucao da funcao, podera
haver perda de dados ou ate mesmo perda do
arquivo;
A sintaxe da funcao e:
fclose(FILE *stream);
onde: stream e a referencia para o arquivo (arq e o
ponteiro obtido quando o arquivo foi aberto)

(Arquivos)

16 / 57

fclose
Quando a funcao fclose() e executada, gera como
resultado um numero inteiro. Se este numero for
igual a zero, significa que o arquivo foi fechado
corretamente.
Qualquer problema que ocorra com a execucao de
um programa podera corromper, ou seja, danificar os
arquivos que estiverem abertos. Assim, e
aconselhavel que arquivos sejam mantidos abertos o
menor tempo possvel.

(Arquivos)

17 / 57

ferror

A funcao ferror() detecta se ocorreu algum erro


durante uma operacao com arquivos.
A sintaxe e:
ferror(FILE *arq);
A funcao ferror() retorna um numero inteiro e dever
ser chamada logo depois que qualquer outra funcao
for invocada.

(Arquivos)

18 / 57

Arquivos Texto

Os proximos slides apresentam algumas funcoes que


podem ser utilizadas ao se trabalhar com arquivos texto.

(Arquivos)

19 / 57

Gravando caracteres em um
arquivo - fputc
A funcao fputc() escreve um caractere em um
arquivo.
A sintaxe e:
fputc(char ch, FILE *stream);
onde:
ch e o caractere que sera escrito no arquivo;
stream e referencia para o arquivo onde o caractere
sera escrito.

(Arquivos)

20 / 57

Lendo caracteres em um arquivo


- fgetc

A funcao fgetc() le um caractere de um arquivo;


A sintaxe e:
int fgetc(FILE *stream)
onde:
stream e referencia para o arquivo onde o caractere
sera lido.

(Arquivos)

21 / 57

Lendo caracteres em um arquivo


- fgetc
Se a execucao da funcao fgetc() for bem-sucedida,
gerara como retorno o valor do caractere lido;
Este valor podera ser armazenado em uma variavel
int, ja que e um valor ASCII, exigindo a conversao do
valor ASCII para o caractere correspondente, ou em
uma variavel char;
Caso ocorra algum erro na leitura, o valor devolvido
sera EOF.

(Arquivos)

22 / 57

Exemplo:lendo e gravando
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#include <stdio.h>
main() {
FILE *arq;
char caractere;
arq = fopen("arquivo.txt","r");
if (arq != NULL) {
while (!feof(arq)) {
caractere = fgetc(arq);
if (ferror(arq))
printf("\nOcorreu um erro de leitura.");
else {
printf("\nLeitura realizada com sucesso");
printf("\nCaracter lido: %c", caractere);
}
}
fclose(arq);
} else
printf("Ocorreu um erro.");
}

(Arquivos)

23 / 57

Gravando cadeias de caracteres fputs()


A funcao fputs() escreve uma cadeia de caracteres
em um arquivo;
A sintaxe e:
fputs(char *s, FILE *stream);
onde:
s armazena a cadeia de caracteres que sera escrita no
arquivo.
stream e a referencia para o arquivo.

(Arquivos)

24 / 57

Exemplo:fputs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#include <stdio.h>
#include <string.h>
main() {
FILE *arq;
char nome[30];
arq = fopen("sequencia.txt","a");
if (arq != NULL) {
printf("Digite um nome: ");
gets(nome);
while (strcmp(nome, "fim") != 0) {
fputs(strcat(nome,"\n"), arq);
if (ferror(arq))
printf("\nOcorreu um erro na gravao .");
else {
printf(" Gravao realizada com sucesso");
printf("\nDigite um nome: ");
fflush(stdin);
gets(nome);
}
}
fclose(arq);
} else
printf("Ocorreu um erro.");
}
(Arquivos)

25 / 57

Lendo cadeias de caracteres fgets()


A funcao fgets() le uma cadeia de caracteres a partir
de um arquivo;
A sintaxe e:
fgets(char *s, int n, FILE *stream);
onde:
s armazena a cadeia de caracteres que esta escrita no
arquivo.
n indica que a quantidade maxima de caracteres.
stream e a referencia para o arquivo.
(Arquivos)

26 / 57

Exemplo:fgets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#include <stdio.h>
main() {
FILE *arq;
char nome[30];
arq = fopen("sequencia.txt","r");
if (arq != NULL) {
fgets(nome, 30, arq);
if (ferror(arq))
printf("\nOcorreu um erro de leitura.");
while (!feof(arq)) {
printf("\nLeitura realizada com sucesso");
printf("\nCadeia lida: %s", nome);
fgets(nome, 30, arq);
if (ferror(arq))
printf("\nOcorreu um erro de leitura.");
}
fclose(arq);
} else
printf("Ocorreu um erro.");
}

(Arquivos)

27 / 57

Gravando cadeias de caracteres fprintf()


A funcao fprintf() escreve uma cadeia de caracteres
em um arquivo;
A sintaxe e:
fprintf(FILE *stream, char *format, ...);
onde:
stream e a referencia para o arquivo.
format e a formatacao do que sera gravado.
... o conteudo que sera gravado

(Arquivos)

28 / 57

Exemplo:fprintf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#include <stdio.h>
#include <string.h>
main() {
FILE *arq;
char nome[30];
arq = fopen("sequencia.txt","w");
if (arq != NULL) {
printf("Digite um nome: ");
gets(nome);
while (strcmp(nome, "fim") != 0) {
fprintf(arq, "%s\n", nome);
if (ferror(arq))
printf("\nOcorreu um erro na gravao .");
else {
printf(" Gravao realizada com sucesso");
printf("\nDigite um nome: ");
fflush(stdin);
gets(nome);
}
}
fclose(arq);
} else
printf("Ocorreu um erro.");
}
(Arquivos)

29 / 57

Lendo cadeias de caracteres fscanf()


A funcao fscanf() le uma cadeia de caracteres a
partir de um um arquivo;
A sintaxe e:
fscanf(FILE *stream, char *format, ...);
onde:
stream e a referencia para o arquivo.
format e a formatacao do que sera gravado.
... o endereco do conteudo que sofrera a gravacao na
memoria
(Arquivos)

30 / 57

Exemplo:fscanf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#include <stdio.h>
main() {
FILE *arq;
char nome[30];
arq = fopen("sequencia.txt","r");
if (arq != NULL) {
fscanf(arq, "%s", &nome);
if (ferror(arq))
printf("\nOcorreu um erro de leitura.");
while (!feof(arq)) {
printf("\nLeitura realizada com sucesso");
printf("\nCadeia lida: %s", nome);
fscanf(arq, "%s", &nome);
if (ferror(arq))
printf("\nOcorreu um erro de leitura.");
}
fclose(arq);
} else
printf("Ocorreu um erro.");
}

(Arquivos)

31 / 57

Exerccio 1:

Crie um programa que requisite o preenchimento de uma


matriz de i linhas e j colunas e grave essa matriz em um
arquivo. Utilize a funcao fprinf().

(Arquivos)

32 / 57

Exerccio 2:

Considerando o exerccio anterior crie um programa que


carregue uma matriz gravada em um arquivo de texto
para a memoria. Utilize a funcao fscanf().

(Arquivos)

33 / 57

Exerccio 3:

Com base nos exerccios anteriores elabore um novo


programa que crie, preencha e salve uma matriz alocada
dinamicamente. O programa deve ainda possibilitar a
reconstrucao da matriz de maneira dinamica.

(Arquivos)

34 / 57

Arquivos bin
arios
Os proximos slides apresentam as funcoes que podem ser
utilizadas com arquivos binarios.
Em C arquivos textos nao podem ser associados a
um registro (struct), pois armazenam uma sequencia
de caracteres;
Quando isso for necessario devera se trabalhar com
arquivos binarios;
Toda vez que uma operacao de leitura ou de escrita
for realizada, devera ser informado o numero de bytes
que serao lidos ou gravados (sizeof);
(Arquivos)

35 / 57

Escrevendo qualquer tipo de


dado - fwrite
A sintaxe e:
fwrite(void *mem ,size t qtd bytes, size t cont, FILE
*arq);
onde:
mem representa a variavel que armazena o conteudo
a ser gravado no arquivo.
qtd bytes representa o total em bytes que sera
escrito no arquivo.
cont representa o numero de blocos de tamanho
qtd bytes que sera escrito no arquivo.
arq e a referencia para o arquivo.
(Arquivos)

36 / 57

Exemplo:fwrite
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

#include <stdio.h>
typedef struct {
int numero;
char nome[30];
} cliente;
main() {
FILE *cli;
cliente c;
cli = fopen("clientes.dat","ab+");
if (cli != NULL) {
printf("Digite o nmero do cliente: ");
scanf("%d",&c.numero);
printf("Digite o nome do cliente: ");
fflush(stdin);
gets(c.nome);
fwrite(&c, sizeof(cliente), 1, cli);
if (ferror(cli))
printf("\nOcorreu um erro na gravao .");
else
printf("\ nGravao realizada com sucesso.");
fclose(cli);
} else
printf("Ocorreu um erro.");
}

(Arquivos)

37 / 57

Lendo qualquer tipo de dado fread


A funcao fread pode ler qualquer tipo de dado e nao
apenas caracteres ou cadeias de caracteres. A sintaxe
e:
fread(void *mem, size t qtd bytes, size t cont, FILE
*arq);
onde:
mem representa a variavel que ira receber o conteudo
lido do arquivo.
qtd bytes representa o total em bytes que sera lido
do arquivo.
cont representa o numero de blocos de tamanho
qtd
bytes que sera lido do arquivo.
(Arquivos)
38 / 57

Exemplo:fread
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

#include <stdio.h>
typedef struct {
int numero;
char nome[30];
} cliente;
main() {
FILE *cli;
cliente c;
cli = fopen("clientes.dat","ab+");
if (cli != NULL) {
fread(&c, sizeof(cliente), 1, cli);
if (ferror(cli))
printf("\nOcorreu um erro na leitura.");
while (!feof(cli)) {
printf("\n\nNmero do cliente: %d",c.numero);
printf("\nNome do cliente: %s",c.nome);
fread(&c, sizeof(cliente), 1, cli);
if (ferror(cli))
printf("\nOcorreu um erro na leitura.");
}
fclose(cli);
} else
printf("Ocorreu um erro.");
}

(Arquivos)

39 / 57

Reposicionamento do arquivo rewind

A funcao rewind() reposiciona o cursor de volta ao


incio do arquivo.
Sua sintaxe e:
rewind(FILE *arq);

(Arquivos)

40 / 57

Exemplo:rewind
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#include <stdio.h>
typedef struct {
int numero;
char nome[30];
} cliente;
main() {
FILE *cli;
cliente c;
cli = fopen("clientes.dat","ab+");
if (cli != NULL) {
fread(&c, sizeof(cliente), 1, cli);
if (ferror(cli))
printf("\nOcorreu um erro na leitura.");
while (!feof(cli)) {
printf("\n\nNmero do cliente: %d",c.numero);
printf("\nNome do cliente: %s",c.nome);
fread(&c, sizeof(cliente), 1, cli);
if (ferror(cli))
printf("\nOcorreu um erro na leitura.");
}

(Arquivos)

41 / 57

Exemplo:rewind

1
2
3
4
5
6
7
8
9

rewind(cli);
fread(&c, sizeof(cliente), 1, cli);
printf("\n\nNmero do cliente: %d",c.numero);
printf("\nNome do cliente: %s\n",c.nome);
fclose(cli);
} else
printf("Ocorreu um erro.");
getch();
}

(Arquivos)

42 / 57

Movimentando o cursor do
arquivo - fseek
Sua sintaxe e:
fseek(FILE *arq, long qtd bytes, int posicao);
onde:
arq representa o arquivo que sera percorrido pela
funcao fseek.
qtd bytes
representa a quantidade de bytes que o cursor sera
movimentado a partir de posicao.
posicao representa o ponto a partir do qual a
movimentacao sera executada, podendo assumir tres
valores: 0, 1, 2.
(Arquivos)

43 / 57

Movimentando o cursor do
arquivo - fseek
fseek(arq, i, 0); posiciona o cursor no byte de numero
i;
fseek(arq, i, 1); desloca o cursor i posicoes `a frente
da posicao atual (o valor i pode ser negativo);
fseek(arq, -i, 2); desloca o cursor i bytes antes do fim
do arquivo; caso o valor de i seja zero, ele vai para o
fim;

(Arquivos)

44 / 57

Exemplo:fseek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include <stdio.h>
typedef struct {
int numero;
char nome[30];
} cliente;
main() {
FILE *cli;
cliente c;
cli = fopen("clientes.dat","ab+");
if (cli != NULL) {
fread(&c, sizeof(cliente), 1, cli);
if (ferror(cli))
printf("\nOcorreu um erro na leitura.");

(Arquivos)

45 / 57

Exemplo:fseek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

while (!feof(cli)) {
printf("\n\nNmero do cliente: %d",c.numero);
printf("\nNome do cliente: %s",c.nome);
fread(&c, sizeof(cliente), 1, cli);
if (ferror(cli))
printf("\nOcorreu um erro na leitura.");
}
fseek(cli, 0, 0);
fread(&c, sizeof(cliente), 1, cli);
printf("\n\nNmero do cliente: %d",c.numero);
printf("\nNome do cliente: %s",c.nome);
fseek(cli, sizeof(cliente), 1);
fread(&c, sizeof(cliente), 1, cli);
printf("\n\nNmero do cliente: %d",c.numero);
printf("\nNome do cliente: %s",c.nome);
fseek(cli, sizeof(cliente)*-1, 2);
fread(&c, sizeof(cliente), 1, cli);
printf("\n\nNmero do cliente: %d",c.numero);
printf("\nNome do cliente: %s",c.nome);
fclose(cli);
} else
printf("Ocorreu um erro.");
}

(Arquivos)

46 / 57

Apagando arquivos - remove


A funcao remove() apaga um arquivo.
A sintaxe e:
remove(char *nome arq);
onde:
nome arq indica o nome fsico do arquivo que sera
removido.
Exemplo:
remove("c:\dir1\subdir1\arquivo.dat");

(Arquivos)

47 / 57

Renomeando arquivos - rename


A funcao rename() renomeia um arquivo.
A sintaxe e:
rename(char *nome atual, char *nome novo);
onde:
nome arq indica o nome fsico atual do arquivo.
nome novo indica o novo nome fsico que se pretende
dar ao arquivo.
Exemplo:

rename("c:\dir1\subdir1\arquivo.dat", "c:\dir1\subdir1\novo.d

(Arquivos)

48 / 57

Obtendo a posi
c
ao corrente de
um arquivo
A funcao ftell() indica a posicao corrente do ponteiro
do arquivo.
A sintaxe e:
ftell(FILE *arq);
Exemplo:
int tamanho=0;
Tamanho = ftell(arq);

(Arquivos)

49 / 57

Exerccio 4:

(Arquivos)

50 / 57

Exerccio 5:

Elabore um sistema que possibilite a criacao e a insercao


de nos em uma lista encadeada em memoria e tambem a
persistencia dessa lista em um arquivo binario. Utilize
como elemento do no um TAD simples, por exemplo, um
TAD composto por um codigo e um nome.

(Arquivos)

51 / 57

Exerccio 6:

Complemente o exerccio anterior de modo que o arquivo


binario utilizado na persistencia possa ser lido e o seu
conteudo transferido para a memoria na forma de uma
lista encadeada.

(Arquivos)

52 / 57

Exerccio 7:
Elabore um sistema que possibilite a criacao e a insercao
de nos em uma lista encadeada em memoria em ordem
alfabetica. A insercao de um no somente deve acontecer
se o mesmo nao existir na lista. Cada no deve ter um
campo elemento para armazenar o conteudo alfanumerico
(vetor de caracteres de N posicoes). Apos a adicao do no
o TAD que contem todas as informacoes de determinada
entidade (por exemplo um aluno) deve ser gravado em um
arquivo. O no deve ainda ter um campo de referencia
(posicao) para o TAD que sera gravado em arquivo.

(Arquivos)

53 / 57

Exerccio 8:

Com base no exerccio anterior elabore uma funcao que


restaure a lista a partir do arquivo. Lembre que a
reconstrucao da lista deve acontecer em ordem alfabetica.

(Arquivos)

54 / 57

Exerccio 9:

Complemente o exerccio anterior implementando uma


funcao que a partir da lista em memoria leia um
determinado registro do arquivo (salvo no exerccio 7) e
imprima os campos desse registro.

(Arquivos)

55 / 57

Exerccio 10:
Complemente o exerccio anterior implementando uma
funcao que possibilite a atualizacao das informacoes de
determinado TAD que nao fazem parte da chave/campo
utilizada na composicao da lista. Para tal siga os
seguintes passos:
Localize o registro que se deseja alterar; Abra o arquivo
de dados; Obtenha o registro utilizando o campo posicao
da lista; Atualize as informacoes no registro recuperado;
Desloque o cursor para a posicao do registro desejado;
Armazene novamente o registro na mesma posicao; Feche
o arquivo de dados.
(Arquivos)

56 / 57

Exerccio 11:
Complemente o exerccio anterior implementando uma
funcao que possibilite a eliminacao de determinado no e
do registro correspondente de maneira logica. Para tal, o
TAD deve agora conter um campo de controle para
informar se este e valido ou nao (int ou char). Os
seguintes passos devem ser considerados:
Localize o registro que se deseja alterar; Abra o arquivo
de dados; Obtenha o registro utilizando o campo posicao
da lista; Posicione o cursor no registro desejado; Atualize
a informacao no campo de controle; Armazene novamente
o registro na mesma posicao; Feche o arquivo de dados.
(Arquivos)

57 / 57

Potrebbero piacerti anche