SOP-arquivos
Arquivos na linguagem C
Para um programador, arquivos são repositórios permanentes de dados, os quais usualmente ficam em midia não volátil (disco rígido, CD ou DVD, pendrive, e outros). Arquivos servem para guardar informações que devem continuar a existir mesmo que termine o processo que as criou. Um exemplo é a agenda, cujo conteúdo deve ser preservado para futuras consultas e modificações. Mas além de serem depósitos de dados, arquivos possuem características bem definidas do ponto de vista de programação.
Um arquivo é uma sequência de bytes, que pode ser acessada, lida e modificada por meio de funções específicas existentes na biblioteca padrão da linguagem C. Essas funções servem para abrir e fechar um arquivo, ler e escrever uma certa quantidade de bytes, e mudar a posição da próxima leitura ou escrita.
Escrevendo em um arquivo
Abaixo segue um exemplo de um programa para escrever uma linha em um arquivo:
#include<stdio.h>
int main() {
char linha[256];
FILE * arquivo;
printf("Digite uma linha: ");
scanf("%[^\n]", linha);
printf("Vou gravar isto no arquivo teste.txt\n");
arquivo = fopen("teste.txt", "w");
if (arquivo == NULL) {
perror("Nao conseguiu abrir o arquivo");
return 1;
}
fprintf(arquivo, "%s\n", linha);
fclose(arquivo);
printf("Pronto ... veja o arquivo teste.txt !\n");
}
Esse pequeno programa evidencia que trabalhar com arquivos é muito parecido a trabalhar com escrita na tela e leitura do teclado. Mas primeiro deve-se focar nas linhas do programa que têm relação direta com arquivos. Para começar, um arquivo é referenciado por uma variável do tipo FILE *:
FILE * arquivo;
Em seguida, o arquivo a ser lido ou escrito deve ser aberto, usando-se a função FILE * fopen(char * nome_arquivo, char * modo):
arquivo = fopen("teste.txt", "w");
Como se pode ver, a função fopen precisa de dois parâmetros do tipo char * (quer dizer, dois parâmetros string). O primeiro é o caminho do arquivo a ser aberto, e o segundo é o modo de abertura (o que se pretende fazer com ele: ler, escrever, adicionar dados ao final, ler e escrever). No exemplo acima, vai-se abrir o arquivo teste.txt para escrita (modo "w", de write). O valor de retorno de fopen é do tipo FILE *, e corresponde a uma descrição do arquivo que foi aberto. Caso aconteça algum erro (ex: não há permissão para criar o arquivo), fopen retorna o valor NULL. O exemplo testa se isto acontece da seguinte forma:
if (arquivo == NULL) {
perror("Nao conseguiu abrir o arquivo");
return 1;
}
Uma vez o arquivo estando aberto para escrita, pode-se escrever nele usando-se a função fprintf. Essa função é idêntica à função printf que se usa para escrever na tela. Porém fprintf precisa de um parâmetro adicional, deve ser a variável que corresponde ao arquivo aberto (primeiro parâmetro da função):
fprintf(arquivo, "%s\n", linha);
Finalmente, quando não se quer mais escrever no arquivo deve-se chamar a função fclose para fechá-lo:
fclose(arquivo);
Lendo uma linha de um arquivo
A leitura de um arquivo é parecida, com algumas pequenas modificações em sua abertura (deve-se indicar que o mode de operação será "r", de "read"), e usando-se a função fscanf para ler dados do arquivo. O exemplo abaixo mostra um programa para ler a primeira linha de um arquivo:
#include<stdio.h>
int main() {
char linha[1024];
char nome[256];
FILE * arquivo;
printf("Digite o nome de um arquivo: ");
scanf("%s", nome);
printf("Vou mostrar a primeira linha do arquivo %s\n", nome);
arquivo = fopen(nome, "r");
if (arquivo == NULL) {
perror("Ops ... erro ao acessar esse arquivo: ");
return 1;
}
fgets(linha, 1024, arquivo);
fclose(arquivo);
printf("Eis a primeira linha do arquivo: \n\n%s\n\n", linha);
}
Como adiantado, na abertura com fopen deve-se usar o valor "r" para o modo:
arquivo = fopen(nome, "r");
Já a leitura de uma linha pode ser feita mais facilmente com a função fgets:
fgets(linha, 1024, arquivo);
A função char * fgets(char * resultado, int max_caracteres, FILE * arquivo) lê uma linha de um arquivo com até max_caracteres e a guarda na variável passada no parâmetro resultado. No exemplo acima, fgets lê uma linha com até 1024 caracteres e a guarda na variável linha.
Lendo todas as linhas de um arquivo
Nesse próximo exemplo, abre-se um arquivo para leitura e lêem-se todas suas linhas, mostrando-as na tela:
#include<stdio.h>
int main() {
char linha[1024];
char nome[256];
char * ok;
FILE * arquivo;
printf("Digite o nome de um arquivo: ");
scanf("%s", nome);
printf("\nVou mostrar todas as linhas do arquivo %s\n\n", nome);
arquivo = fopen(nome, "r");
if (arquivo == NULL) {
perror("Ops ... erro ao acessar esse arquivo: ");
return 1;
}
do {
ok = fgets(linha, 1024, arquivo);
if (ok != NULL) printf("%s", linha);
} while (! feof(arquivo));
fclose(arquivo);
}
A diferença em relação ao exemplo anterior está na sequência que lê as linhas do arquivo:
do {
ok = fgets(linha, 1024, arquivo); // Lê a próxima linha do arquivo
if (ok != NULL) printf("%s", linha); // se conseguiu ler algo, mostra na tela
} while (! feof(arquivo)); // para se chegou ao fim de arquivo
Há algumas novidades aqui:
- O valor de retorno de fgets é testado quanto a sua validade: a função fgets retorna o valor NULL se não conseguiu ler algo do arquivo. Isto pode ter ocorrido por um erro de leitura (ex: disco com defeito) ou porque se chegou ao fim do arquivo, e assim nada mais existe para ser lido. Esse teste aparece na linha: .
if (ok != NULL) printf("%s", linha)
- A leitura continua enquanto não se chegar ao fim de arquivo: o teste de fim de arquivo se faz com a função int feof(FILE * arquivo), que retorna 0 se ainda não se chegou ao final do arquivo, ou 1 caso contrário. A chamada de feof se faz ao final do laço:
} while (! feof(arquivo));