SOP-arquivos

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar

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:

  1. 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)
    
    .
  2. 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));