Baixe o app para aproveitar ainda mais
Prévia do material em texto
Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica COMPUTAÇÃO BÁSICA Manipulação de Arquivos Prof. Bruno Macchiavello (bruno@cic.unb.br) Universidade de Brasília – UnB Instituto de Ciências Exatas – IE Departamento de Ciência da Computação – CIC Prof. Bruno Macchiavello 1 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Introdução • A linguagem C não possui nenhum comando de entrada/saída • Todas as operações de entrada/saída ocorrem mediante chamadas a funções da biblioteca C padrão. Exemplo: � Os comandos de entrada e saída que usamos até o momento foram da biblioteca STDIO.H: • printf – mostra dados formatados no vídeo • scanf – lê dados formatados digitados do teclado • Embora tal característica possa, a primeira vista, parecer uma desvantagem, na verdade ela permite que o sistema de arquivos de C seja extremamente poderoso e flexível Prof. Bruno Macchiavello 2 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Introdução • Porém, os dados podem também ser lidos e gravados em arquivos (em geral em discos). • Um arquivo em disco é um espaço com diversas características físicas, dependendo do tipo de dispositivo que é usado (disquete, disco rígido, CD, etc.). • Um arquivo em disco, pode ser visto como um espaço sequêncial (“stream”) onde são lidos ou gravados os dados. A cada arquivo está associado um nome, pelo qual o mesmo é conhecido externamente, isto é, o nome que consta no diretório do disco. • Uma vez que um arquivo é uma sequência de bytes temos o marcador do final desse arquivo que é: EOF (EndOfFile) Prof. Bruno Macchiavello 3 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Tipos de Arquivos • O sistema de entrada/saída de arquivos em C permite que os dados possam ser transferidos na sua representação binária interna ou em um formato de texto legível por humanos. Isso torna fácil criar arquivos que satisfaçam qualquer necessidade Prof. Bruno Macchiavello 4 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Tipos de Arquivos • TEXTO: � são gravados caracteres, ou seja um texto mesmo. Semelhante ao programa.c, que é um arquivo de texto, o qual podemos visualizar facilmente com um editor de texto. • BINÁRIO: � são gravados os dados como estariam na memória. Por exemplo, uma variável inteira é gravada com 4 bytes com o conteúdo exato que está na memória. Não conseguimos visualizar simplesmente com um editor de texto, é necessário através de um programa abrí-lo e fazê-lo ser mostrado na tela. Prof. Bruno Macchiavello 5 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica I/O ANSI vs I/O UNIX • O padrão C ANSI define um conjunto completo de funções de I/O que pode ser utilizado para ler e escrever qualquer tipo de dado. • O antigo padrão C UNIX contém dois sistemas• O antigo padrão C UNIX contém dois sistemas distintos de rotinas que realizam operações de I/O �O primeiro método assemelha-se vagamente ao definido pelo padrão C ANSI e é denominado sistema de arquivo com buffer (ou formatado ou de alto nível) �O segundo é o sistema de arquivo tipo UNIX (não formatado ou sem buffer) definido apenas sobre o antigo padrão UNIX. Prof. Bruno Macchiavello 6 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica I/O ANSI vs I/O UNIX • O padrão ANSI não define o sistema sem buffer porque: �os dois sistemas são amplamente redundantes �sistema de arquivos tipo UNIX pode não ser relevante a certos ambientes • Nesta disciplina daremos ênfase ao sistema de arquivo C ANSI Prof. Bruno Macchiavello 7 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica I/O ANSI C vs I/O C++ • C++ suporta todo o sistema de arquivos definido pelo C ANSI • Entretanto, C++ também define seu próprio• Entretanto, C++ também define seu próprio sistema de I/O, orientado a objetos, que inclui tanto funções quanto operadores de I/O. • O sistema de I/O C++ duplica por completo a funcionalidade do sistema de E/S C ANSI Prof. Bruno Macchiavello 8 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Stream e Arquivos • O sistema de I/O de C fornece uma interface consistente ao programador C, independentemente do dispositivo real que é acessado. • Este sistema (que é uma abstração) é chamado de stream e o dispositivo real é chamado de arquivo . • OBS: daí decorre que, em C, todos os dispositivos são encarados como arquivos Prof. Bruno Macchiavello 9 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Stream • O sistema de arquivos de C é projetado para trabalhar com uma ampla variedade de dispositivos, incluindo: � terminais,� terminais, � acionadores de disco � acionadores de fita. • Embora cada um dos dispositivos seja muito diferente, o sistema de arquivo com buffer transforma-os em um dispositivo lógico chamado de stream. Prof. Bruno Macchiavello 10 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Stream • Todas as streams comportam-se de forma semelhante. • Pelo fato de as streams serem totalmente• Pelo fato de as streams serem totalmente independentes do dispositivo, a mesma função pode escrever em um arquivo em disco ou em algum outro dispositivo, como o console. Prof. Bruno Macchiavello 11 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Arquivo • Em C, um arquivo pode ser qualquer coisa, desde um arquivo em disco até um terminal ou uma impressora. • Associa-se um stream com um arquivo específico realizando uma operação de abertura. • Uma vez o arquivo aberto, informações podem ser trocadas entre ele e o seu programa. Prof. Bruno Macchiavello 12 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Arquivos • Nem todos os arquivos apresentam os mesmos recursos. • Por exemplo, um arquivo em disco pode• Por exemplo, um arquivo em disco pode suportar acesso aleatório (seqüencial), enquanto um teclado não pode. • Isso releva um ponto importante sobre o sistema de I/O de C: todas as streams são iguais, mas não todos os arquivos. Prof. Bruno Macchiavello 13 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Arquivos • Todos os arquivos são fechados automaticamente quando o programa termina normalmente, com main() retornando ao sistema operacional ou uma chamada a exit(). • Cada stream associada a um arquivo tem uma estrutura decontrole de arquivo do tipo FILE. Esta estrutura é definida no cabeçalho stdio.h. Prof. Bruno Macchiavello 14 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Ponteiro de um Arquivo • Um ponteiro de arquivo é um ponteiro para informações que definem várias coisas sobre o arquivo: nome, status e a posição atual do arquivo • Um ponteiro de arquivo é uma variável ponteiro do tipo FILE.tipo FILE. • Para ler ou escrever arquivos, seu programa precisa usar ponteiros de arquivo. Para obter uma variável ponteiro de arquivo, use o comando: FILE *fp; Prof. Bruno Macchiavello 15 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Antes de ler ou gravar em algum arquivo precisamos ter certeza de algumas coisas: � Onde se encontra o arquivo?� Onde se encontra o arquivo? � O arquivo já existe, e vamos apenas abrí-lo? � O arquivo não existe e vamos criá-lo? � O arquivo já existe mas vamos recriá-lo? Prof. Bruno Macchiavello 16 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Assim, temos a função fopen (file Open), que possui dois parâmetros, um o nome do arquivo, e o segundo o tipo de operação que faremos com ele. • Por exemplo: Prof. Bruno Macchiavello 17 FILE *fp; char nomeArquivo[] = “c:\arquivo.txt”; fp = fopen(nomeArquivo, “w”); Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Tabela de funcionalidades: • Nota: sempre que cria-se um arquivo já existente conteúdo dele é apagado Prof. Bruno Macchiavello 18 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Uma melhor maneira de abrir um arquivo é: FILE *fp; if((fp = fopen( “arquivo1”, “w”)) == NULL ) { printf(“nao foi possivel criar o arquivo\n”);printf(“nao foi possivel criar o arquivo\n”); exit(1); } • Neste segundo caso, qualquer erro na abertura do arquivo será detectado (e.g., disco cheio ou protegido contra gravação). Prof. Bruno Macchiavello 19 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Caso não se estejamos certos se o arquivo já existe, e se existir não queremos apagar seu conteúdo, podemos usar a opção de ANEXAR (a), ou a seguinte código: FILE *fp; char nomeArquivo[] = “c:\arquivo.txt”; Prof. Bruno Macchiavello 20 char nomeArquivo[] = “c:\arquivo.txt”; if (fopen(nomeArquivo, “r+”) == NULL) { fp = fopen(nomeArquivo, “w”); } else { fp = fopen(nomeArquivo, “r+”); } Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Da mesma forma que devemos abrir um arquivo utilizando a função fopen, devemos fechá-lo quando não formos mais utilizá-lo, pois assim realmente garantimos que o arquivo será salvo em disco, e não ficará simplesmente no bufferem disco, e não ficará simplesmente no buffer (região de memória). • Para isso utilizamos o comando fclose, da seguinte forma: fclose (fp); /* fp é o ponteiro para o arquivo*/ Prof. Bruno Macchiavello 21 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Para fazermos a leitura e gravação em uma arquivo, devemos utilizar as funções fprintf, e fscanf, respectivamente. • Essas funções tem como parâmetros, o ponteiro do arquivo, os tipos dos dados, e depois, os endereços das variáveis que utilizaremos para representar esses valores.utilizaremos para representar esses valores. � Por exemplo, queremos ler números inteiros de um arquivo: � Para escrever no arquivo: Prof. Bruno Macchiavello 22 int numero1, numero2, numero3; fscanf(fp, “%d %d %d”, &numero1, &numero2, &numero3); fprintf(fp, “%d %d %d”, &numero1, &numero2, &numero3); Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Trabalhando com Arquivos • Uma vez que utilizamos um ponteiro para ir lendo cada linha do arquivo, e que lemos para arquivos TEXTO como se fosse um vetor, precisamos muitas vezes reposicionar esse ponteiro no inicio do arquivo. Para isso ponteiro no inicio do arquivo. Para isso podemos utilizar a função rewind, da seguinte forma: rewind (fp); /*retorna a posição corrente do arquivo para o início*/ Prof. Bruno Macchiavello 23 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Exemplo: um programa que escreve a string “Meu primeiro programa com arquivo texto” em um arquivo, em seguida lê a mesma (do arquivo) e mostra seu conteúdo na tela: #include <stdio.h> #include <string.h> int main (){ FILE *fp; char string[50]; char nomeArquivo[50]; strcpy(nomeArquivo, "arquivo.txt"); if (fopen(nomeArquivo, "r+") == NULL) { fp = fopen(nomeArquivo, "w"); } else { Prof. Bruno Macchiavello 24 } else { fp = fopen(nomeArquivo, "r+"); } strcpy(string,"Meu primeiro programa com arquivo texto"); fprintf(fp, "%s", string); fclose(fp); fopen(nomeArquivo,"r+"); strcpy(string," "); /*mudamos o conteudo da variavel string*/ fscanf(fp, "%s", string); printf("string do arquivo e: %s\n", string); getchar(); fclose(fp); return 0; } Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Exemplo: um programa que escreve a string “Meu primeiro programa com arquivo texto” em um arquivo, em seguida lê a mesma (do arquivo) e mostra seu conteúdo na tela: #include <stdio.h> #include <string.h> int main (){ FILE *fp; char string[50]; char nomeArquivo[50]; strcpy(nomeArquivo, "arquivo.txt"); if (fopen(nomeArquivo, "r+") == NULL) { fp = fopen(nomeArquivo, "w"); } else { Cria o arquivo e abre para gravação Testa se o arquivo existe Prof. Bruno Macchiavello 25 } else { fp = fopen(nomeArquivo, "r+"); } strcpy(string,"Meu primeiro programa com arquivo texto"); fprintf(fp, "%s", string); fclose(fp); fopen(nomeArquivo,"r+"); strcpy(string," "); /*mudamos o conteudo da variavel string*/ fscanf(fp, "%s", string); printf("string do arquivo e: %s\n", string); getchar(); fclose(fp); return 0; } Grava no arquivo Fecha o arquivo Abre o arquivo Lê do arquivo Abre o arquivo para gravação Fecha o arquivo Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Exemplo: um programa que escreve a string “Meu primeiro programa com arquivo texto” em um arquivo, em seguida lê a mesma (do arquivo) e mostra seu conteúdo na tela: #include <stdio.h> #include <string.h> int main (){ FILE *fp; char string[50]; char nomeArquivo[50]; strcpy(nomeArquivo, "arquivo.txt"); if (fopen(nomeArquivo, "r+") == NULL) { fp = fopen(nomeArquivo, "w"); } else { Uma vez que fechamos o arquivoe o reabrimos não há necessidade de usarmos o rewind() para o ponteiro voltar a posicao original, pois quando abrimos o arquivo ele já está lá. Prof. Bruno Macchiavello 26 } else { fp = fopen(nomeArquivo, "r+"); } strcpy(string,"Meu primeiro programa com arquivo texto"); fprintf(fp, "%s", string); fclose(fp); fopen(nomeArquivo,"r+"); strcpy(string," "); /*mudamos o conteudo da variavel string*/ fscanf(fp, "%s", string); printf("string do arquivo e: %s\n", string); getchar(); fclose(fp); return 0; } Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Arquivo Texto • OBS sobre o exemplo do slide anterior: � Note que a saída resultante é simplesmente a palavra Meu, pois num arquivo do tipo texto, os espaços indicam um novo registro (dado). � Para solucionar isso, temos duas alternativas: 1. Fazer um loop para para ler as strings do arquivo enquanto 1. Fazer um loop para para ler as strings do arquivo enquanto não chegar no final do mesmo (veja exemplo no próximo slide) 2. Utilizar o comando fscanf da seguinte forma: fscanf(fp, "%[^\n]s", string); (veja o exemplo dois slides adiante) � Observe que podemos abrir o arquivo.txt usando um NotePad e é possível visualizar o conteúdo que foi escrito nele. Prof. Bruno Macchiavello 27 Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Exemplo ARQUIVO TEXTO: um programa que escreve a string “Meu primeiro programa com arquivo texto” em um arquivo, em seguida lê a mesma (do arquivo) e mostra seu conteúdo na tela: #include <stdio.h> #include <string.h> int main (){ FILE *fp; char string[50]; char nomeArquivo[50]; strcpy(nomeArquivo, "arquivo.txt"); if (fopen(nomeArquivo, "r+") == NULL) { fp = fopen(nomeArquivo, "w"); Prof. Bruno Macchiavello 28 fp = fopen(nomeArquivo, "w"); } else { fp = fopen(nomeArquivo, "r+"); } strcpy(string,"Meu primeiro programa com arquivo texto"); fprintf(fp, "%s", string); fclose(fp); fopen(nomeArquivo,"r+"); strcpy(string," "); /*mudamos o conteudo da variavel string*/ while (fscanf(fp, "%s", string) != EOF) { printf("%s ", string); getchar(); } fclose(fp); return 0; } Note que cada vez que chamamos a funcao fscanf ela incrementa automaticamente o ponteiro do arquivo Departamento de Ciência da ComputaçãoDepartamento de Ciência da Computação Universidade Universidade de de BrasíliaBrasília Computação BásicaComputação Básica Exemplo ARQUIVO TEXTO: um programa que escreve a string “Meu primeiro programa com arquivo texto” em um arquivo, em seguida lê a mesma (do arquivo) e mostra seu conteúdo na tela: #include <stdio.h> #include <string.h> int main (){ FILE *fp; char string[50]; char nomeArquivo[50]; strcpy(nomeArquivo, "arquivo.txt"); if (fopen(nomeArquivo, "r+") == NULL) { fp = fopen(nomeArquivo, "w"); Prof. Bruno Macchiavello 29 fp = fopen(nomeArquivo, "w"); } else { fp = fopen(nomeArquivo, "r+"); } strcpy(string,"Meu primeiro programa com arquivo texto"); fprintf(fp, "%s", string); fclose(fp); fopen(nomeArquivo,"r+"); strcpy(string," "); /*mudamos o conteudo da variavel string*/ fscanf(fp, "%[^\n]s", string); fclose(fp); return 0; } Lê e escreve toda string de uma vez.
Compartilhar