ARQUIVOS

 

Um conjunto de bytes referenciados por um único nome, reunidos e armazenados num disco, constitui um arquivo. A linguagem C permite que se manipulem arquivos em discos, possibilitando a realização de operações básicas tais como: criação e remoção de um arquivo físico, inserção, alteração, exclusão e consulta sobre os dados armazenados em um arquivo, além da exibição (na tela ou em formato impresso) do conteúdo de um arquivo, entre outras manipulações.

 

A vantagem da gravação dos dados em disco é que estes não serão perdidos depois do término da execução do programa. Os computadores armazenam arquivos em dispositivos secundários de armazenamento, que permanecem, persistentemente, disponíveis para o uso de um programa computacional, ou diretamente do próprio usuário.

 

Arquivo de Registro

 

Na prática da programação em C os arquivos de uso mais comum são os arquivos que armazenam dados oriundos de uma estrutura. Por exemplo, um sistema que gerencie os dados referentes aos funcionários de uma empresa deve manipular um arquivo que armazene para cada funcionário, um código de identificação ou matrícula funcional, o nome do funcionário, o tempo de trabalho na empresa, data de entrada e/ou saída da empresa, salário, etc. No momento da inserção dos dados, eles podem ser armazenados numa estrutura heterogênea (struct) em memória e logo após em um arquivo de maneira persistente (que não seja perdido quando programa terminar).

 

Para facilitar o gerenciamento dos dados referentes a um registro e possibilitar a certificação de que o registro que se pretende manipular está armazenado no arquivo é selecionado um ou mais campos cujos valores sejam distintos entre si, sendo o valor deste campo um identificador único do referido registro. O campo selecionado como identificador único dos registros de um arquivo é chamado de chave. Esta pode ser a principal função de dados como: CPF, matrículas, placas de veículos, entre vários outros pertencentes ao seu dia-a-dia.

 

A linguagem C divide as categorias de acesso a disco em dois grandes grupos chamados de alto-nível, ou leitura e gravação bufferizada.

 

Leitura e Gravação em Disco-Alto-Nível

 

A linguagem C disponibiliza quatro diferentes opções de acesso bufferizado de arquivos:

 
  • 1º. Os dados são lidos e escritos um caractere por vez;
  •  
  • 2º. Os dados são lidos e escritos em conjunto de caracteres (string);
  •  
  • 3º. Os dados são lidos e escritos de modo formatado;
  •  
  • 4º. Os dados são lidos e escritos em bloco ou registros formatados, sendo eles um grupo de dados de tamanho fixo que serão armazenados em uma sequência de dados por itens similares.
  •  
 

Em contrapartida a leitura e gravação em baixo-nível oferece somente um único modo de acesso ao arquivo.

 

Texto x Binário

 

Conforme a abertura de um arquivo ele poderá ser classificado em binário ou texto.

 

Um arquivo aberto em modo texto é interpretado em C como sequência de caracteres agrupados em linhas, sendo estas linhas separadas por um único caractere denominado caractere de nova linha ou LF (código ASCII 10 decimal).

 

No sistema operacional DOS (Disk Operation System) o arquivo aberto em modo texto é interpretado como sequências de caracteres agrupadas em linhas. Neste caso as linhas são separadas por dois caracteres, o caractere 13 decimal, ou CR/LF quando o arquivo é gravado em disco.

 

Cabe ao compilador C converter o par CR/LF em um único caractere de nova linha quando um arquivo aberto em modo texto é lido, e converte o caractere de nova linha no par CR/LF para os dados serem gravados em arquivo em um dispositivo secundário de armazenamento (exemplo: disco).

 

Uma indicação de fim de arquivo é enviada pelo DOS aos programas que estão acessando estes arquivos. Isso ocorre quando seu código final é encontrado. Se um arquivo é aberto em modo texto, ele reconhece a indicação de fim de arquivo enviada pelo DOS.

 

O modo binário torna-se mais simples que o modo texto pelo fato de não ser realizada nenhuma conversão de caractere. Qualquer caractere é lido ou gravado sem alteração e a indicação de fim de arquivo não é reconhecida, sendo interpretada como outro caractere qualquer.

 

O modo binário armazena números no disco da mesma forma em que estes encontram-se na memória, dois bytes para um inteiro, quatro para float, etc. Já no modo texto os números são agrupados como cadeias de caracteres (string).

 

Leitura e Gravação em Alto-Nivel

 

Abrindo Arquivos em Disco

 

No trabalho com arquivos em disco, o sistema operacional e seu programa devem participar em conjunto com informações específicas sobre o arquivo. Antes que o programa seja acessado as informações referentes ao arquivo já devem estar presentes no mesmo.

 

Em geral, as informações necessárias são reunidas numa estrutura heterogênea de dados (struct). A declaração desta estrutura está contida na biblioteca "stdio.h" que acompanha o compilador C padrão, sendo seu nome definido como um tipo de dado FILE, criado por meio da instrução typedef. Essa instrução possibilita a criação de novos tipos de dados, por exemplo, na declaração:

 

typedef float real;

 

Essa declaração indica que o identificador real é um sinônimo de float, facilitando novas declarações para variáveis similares como em:

 

real valorTotal, matriz[5];

 

Com estruturas heterogêneas o typedef pode ser usado das seguintes formas: Por exemplo, em declarações como:

 

              struct funcionário
              {
                  char nome[30];
                 
                  int matriculaFuncional;
              };
                 
           
 

typedef struct funcionario registro;

 

registro reg1, reg2; // declaração de 2 variáveis do tipo registro

 

Esta instrução typedef também pode ser usada diretamente como:

 

            typedef struct funcionario{

                char nome[30];

                int matriculaFuncional;

            } registro;
               
          
 

registro reg1, reg2; // declaração de 2 variáveis do tipo registro

 

A referência a um campo específico da estrutura se faz com a posição do identificador da variável estrutura e o identificador do campo, separados por um ponto. Para declaração anterior seriam possíveis os comandos:

 
  • registro.reg1=1200;
  • printf("Informe a matrícula :\n");
  • scanf("%s", registro.matriculaFuncional);
  • printf("\n Informe o nome:\n");
  • gets(registro.nome);
 

Observe abaixo um fragmento da biblioteca stdio.h para compreender melhor o tipo FILE.

 
          #define abre_max  10
          
          typedef struct{
                
                short level;   /*completa /limpa nível de buffer*/
                unsinged flags;   /*status do arquivo*/ 
                char fd;       /*identificador de arquivo*/
                unsigned char hold;  /*devolve char se não houver buffer*/
                short  bsize; /*tamanho do buffer*/
                unsigned char *buffer; /*buffer para transferência de dados*/
                unsigned char *curp; /*posição corrente do ponteiro*/
                unsigned istemp; /*indicador de arquivo temporário*/
                short token; /*usado para checagem de validade*/
                
          }FILE;    /*este é o objeto FILE*/
          
          extern FILE     _streams[abre_max];
 
          
 

Como cada arquivo necessita de informações semelhantes, é declarada na stdio.h uma matriz de estruturas (struct) FILE denominadas "_streams[]". No exemplo acima, "abre_max" corresponde a um valor constante simbólico com capacidade de abertura de no máximo 10 arquivos simultâneos. O número definido para a constante depende das restrições do sistema operacional e das considerações realizadas no projeto compilado.

 

A struct FILE possui elementos com informações referentes ao arquivo utilizado, tais como: localização de seus dados, posição do ponteiro, tamanho atual, indicação se o arquivo está sendo lido ou gravado, etc.

 

A função responsável pela abertura de um arquivo é fopen(), cabendo a ela a função de preencher a estrutura FILE com os dados necessários para comunicação do sistema operacional e o programa que o acessará. Ela sempre retorna um ponteiro do tipo FILE que aponta para a localização desta struct na memória. Se, por alguma razão o arquivo não for criado, a função fopen() retorna o valor da macro NULL.

 

Abrindo o Arquivo

 
 

Ao se abrir um arquivo, caso tal operação seja bem sucedida, ocorrerá o retorno de um ponteiro para a estrutura FILE. Portanto, cada arquivo que é aberto tem uma estrutura FILE criada na memória e um ponteiro guardando seu endereço inicial.

 

A inclusão da biblioteca stdio.h é necessária sempre que for criar um programa em alto-nível, pois a estrutura FILE é declarada nessa biblioteca.

 

Para gerar um código de programa que abre um arquivo, o compilador precisa conhecer três itens:

 
  • 1º. O nome físico do arquivo que será usado;
  • 2º. O tipo ou modo de abertura;
  • 3º. Onde serão guardadas as informações sobre o arquivo aberto.
 

Exemplo:

 

ponteiro = fopen("arquivo.txt","w");

 

Nesse exemplo o comando informa ao sistema operacional que deverá realizar a abertura de arquivo para escrita (o modo w especifica abertura de arquivo para escrita) chamado arquivo.txt. Por não estar especificado o local de gravação será no disco corrente, ou seja, onde o programa está sendo executado (pode ser informado o caminho completo ou o dispositivo de acesso que se deseja que o sistema operacional grave os dados, como em:c:\temp\teste\arquivo.txt).

 

A função fopen() retorna um ponteiro para a estrutura FILE, onde estão guardadas as informações sobre o arquivo, que será armazenado na variável ponteiro declarada como um ponteiro do tipo FILE.

 

Na abertura do arquivo, dois modificadores poderão ser empregados junto ao tipo. A letra "b" especifica que o arquivo será do tipo binário e a letra "t" especifica a abertura de arquivo no formato texto.

 

Lista de abertura de arquivo da função >fopen():

 
r Abrir um arquivo para leitura. O arquivo deve estar presente no disco.  Geralmente é utilizado para ler os dados do arquivo existente.
w Abrir um arquivo para gravação. Se o arquivo já existir, ele será destruído e reinicializado, caso contrário, será criado. Usado geralmente para criar arquivos temporários.
a Abrir um arquivo para gravação. Os dados serão adicionados ao fim do arquivo existente, ou um novo arquivo será criado.
r+ Abrir um arquivo para leitura e gravação. Se o arquivo não existir ele será criado e pode ser atualizado.
w+ Abrir um arquivo para leitura e gravação. Se o arquivo existir ele será destruído e reinicializado. Se não existir, será criado.
a+ Abrir um arquivo para atualizações e para adicionar dados ao fim do arquivo existente ou caso o arquivo não exista um novo arquivo será criado.

 

É importante ressaltar que se deve dedicar especial atenção ao modo de abertura do arquivo, pois todos os programas que acessam arquivos em disco devem verificar se o arquivo foi aberto com sucesso, antes de ler ou escrever nele. Essa precaução irá evitar falha na abertura e gravação durante o trabalho com arquivos. Caso o arquivo não abra seu ponteiro será nulo (NULL).

 

O código do programa abaixo se destina a criação de um arquivo no modo binário:

 
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    // Declarações 
       char nome[15];
       FILE *criaArquivo(char nome[15]);
    // Instruções 
       printf("\n Informe o nome do arquivo:\n");
       gets(nome);
       if(criaArquivo(nome) != NULL)
          printf("\n O arquivo foi criado com sucesso!");
       else
          printf("O arquivo já existia e foi aberto para leitura");
          system("PAUSE");
          return 0;
}
 
FILE *criaArquivo (char nome[15])
{
//Declarações
    FILE *ponteiro;
//Instruções
   ponteiro=fopen(nome,"rb"); //Modo de abertura do arquivo só de leitura binária
   if(ponteiro == NULL)
   {
       ponteiro = fopen(nome,"wb"); // Arquivo pode ser criado sem apagar outro
       return(ponteiro);
   }
   else
   {
       printf("\a Arquivo %s já existe!", nome);
       getche();
   }
}

 

Escrevendo no Arquivo

 

Após a abertura do arquivo para escrita é possível escrever nele de duas formas: caractere a caractere ou organizando os dados em estruturas e gravando-os de uma única vez.

 

Para realizar a gravação de caracteres individuais no arquivo se utiliza a função putc através de um laço de repetição, onde um caractere é gravado toda vez que a função putc é executada neste laço (repetição). Observe o exemplo abaixo:

 

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Declarações
    FILE *ponteiro;
    char letra;
 // Instruções
    ponteiro = fopen("arquivo.txt","wt");
    printf("\n Digite os caracteres ou 's' para sair:\n");
    while((letra = getche()) != 's')
        putc(letra, ponteiro);
    fclose(ponteiro);
}            
 

A gravação de registros num arquivo é feita através da função fwrite() a qual possui quatro parâmetros:

 
  • 1º. Um ponteiro para uma variável do tipo void que receberá o endereço da variável do tipo struct que contém os dados que se quer armazenar;
  • 2º. Um inteiro que receberá o tamanho, em bytes, do registro a ser armazenado;
  • 3º. Um inteiro que receberá o número ou quantidade destes registros que serão armazenados no arquivo;
  • 4º. Um ponteiro de arquivos que receberá o fluxo associado através da função fopen() ao arquivo de disco onde os dados serão armazenados.
 

Exemplo:

 

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
 // Declarações
  typedef struct {
     char matricula[6], nome[40];
     float salario;
  } registro;     // nome do novo tipo de dado somente para este programa
  FILE *ponteiro;
  registro acesso;
  int opcao =1;
 // Instruções
   ponteiro = fopen("arquivo.bin","wb");
   while(opcao != 0)
   {
       fflush(stdin);
       system("cls");
       printf("\n Nome:\n");
       gets(acesso.nome);
       printf("\n Matricula:\n");
       gets(acesso.matricula);
       printf("\n Salário:\n");
       scanf("%f",&acesso.salario);
       system("cls");
       printf("\n Digite: \n'0' para sair \n'1'para continuar\n");
       scanf("%d",&opcao);
       fwrite(&acesso,sizeof(registro),1, ponteiro);
   }
   fclose(ponteiro);
}

 

A função fwrite() retorna o valor do terceiro parâmetro quando há sucesso na gravação no arquivo, senão retornará outro valor, conforme tenha conseguido ou não gravar algum registro no arquivo desejado.

 

O operador sizeof() retorna o tamanho de bytes do parâmetro passado. No exemplo anterior irá retornar 50: 6 bytes de matricula, 40 bytes de nome e 4 bytes de salário.

 

Fechando Arquivo

 

A função utilizada para fechar o arquivo é a fclose(). O fechamento do arquivo após a sua gravação é essencial para a gravação do conteúdo do buffer no disco e para a liberação das áreas de comunicação usadas, a fim de disponibilizá-las a outros arquivos. Estas áreas incluem a estrutura FILE e o buffer. Para evitar erros o arquivo deve ser fechado quando foi confirmado que ele foi aberto.

 

A função exit() também é utilizada para o fechamento de um arquivo, com a distinção que esta irá fechar todos os arquivos abertos e encerrar a execução do programa, devolvendo o controle para o sistema operacional.

 

Exibindo o Conteúde um Arquivo

 

Para acessar o conteúdo de um arquivo é necessário que o conteúdo seja transferido para a memória do computador. A transferência do conteúdo de um arquivo para a memória pode ser feita registro a registro, armazenando cada um deles em uma estrutura, ou através de um conjunto de registros, armazenando-o numa matriz de struct.

 

Essa transferência de registros é feita através da função fread() que apresenta os quatro parâmetros a seguir:

 

  • 1º. Um ponteiro para uma variável do tipo void que receberá o endereço da variável que armazenará os dados contidos no registro do arquivo;
  • 2º. Um inteiro que receberá o tamanho, em bytes, da estrutura que armazenará o registro na memória;
  • 3º. Um inteiro que receberá o número ou quantidade de registros que serão transferidos para a memória (com a transferência de registros um a um essa opção será sempre igual a 1);
  • 4º. Um ponteiro de arquivo que receberá o fluxo associado, através da função fopen(), ao arquivo de disco que contém os registros armazenados de forma persistente.
 

É necessário que o arquivo esteja "aberto para leitura" para a aplicação da função fread(). Quando é feita uma chamada da função fopen() com os argumentos nome do arquivo e modo de abertura, o primeiro registro do arquivo fica disponível para leitura, sendo que após a execução da função fread() o apontador interno do arquivo de leitura e gravação avança, automaticamente, para o próximo registro até percorrer todo o arquivo atingindo o seu final.

 

A função feof() é usada para indicar o fim do arquivo, e tem como parâmetro um ponteiro de arquivo. Ela retornará um número diferente de zero quando o ponteiro de leitura e gravação aponta para o final do arquivo. A marca de fim de arquivo poderá diferenciar de acordo com os diversos sistemas operacionais. Portanto, o valor EOF (End Of File) pode ser qualquer um, sendo aconselhável consultar o sistema operacional utilizado para saber o valor correto, pois o uso do valor -1 (valor usado por vários compiladores) poderá trazer problemas se o programa for transportado para um outro sistema operacional. Pode também ser usada a macro EOF.

 

Exemplo

 

// Função que exibe na tela o conteúdo de um arquivo

#include <stido.h>

void ExibeArquivo()
{
     // Declarações
      FILE *ponteiro;
      struct estrutura  acesso;
      ponteiro = fopen("arquivo.bin","rb");
      while(EOF =! feof(ponteiro)) //O programa será executado enquanto não for o fim 
      {                    //do arquivo, lendo e apresentando seu conteúdo (dados)
         fread(&acesso,sizeof(acesso),1,ponteiro);
         printf("%s\b%s\b%f\n", acesso.matricula, acesso.nome, acesso.salario);
      }
      fclose(ponteiro);
}
 
 

A função fread(), igualmente a fwrite(), retorna o valor do terceiro parâmetro quando há sucesso na leitura de dados do arquivo. É imprescindível que seja validado a fread(), pois na repetição pode ser atingido EOF (fim do arquivo) e o último valor repetir na hora da apresentação erroneamente.

 

A função fputs() é usada para gravar strings de uma só vez em um arquivo de dados. Ela possui dois argumentos, sendo o primeiro a matriz de caracteres que será gravada e o segundo o ponteiro para struct FILE do arquivo a ser gravado.

 

A função fgets() é um complemento da função fputs(), pois ela lê uma linha por vez de um arquivo de texto. Essa função possui três argumentos. O primeiro é um ponteiro para o buffer onde será colocada a linha lida. O segundo é um número inteiro que indica o limite máximo de caracteres a serem lidos, sendo que este total deve ser pelo menos um valor maior que o número de caracteres lidos porque a gets() acrescenta o caractere que marca o final da string (\0) em sua próxima posição livre. O terceiro argumento é um ponteiro para a struct FILE do arquivo lido. A função termina a leitura após ler um caractere de nova linha ('\n') ou um caractere de fim de arquivo (EOF).

 

A função fgets() difere da gets() pelos seguintes pontos:

 
  • 1º. A função gets() recebe a entrada pelo teclado, enquanto a fgets() de um arquivo em disco;
  • 2º. A função gets() termina a leitura quando um caractere de nova linha for lido do teclado (o usuário pressionar <ENTER<>);
  • 3º. O caractere nova linha não é adicionado à string lida. Um caractere (\0) é acrescentado ao final da string. A função fgets() entretanto, inclui o caractere de nova linha e o caractere (\0) ao final da string.
 

Exemplo

 

// Programa que grava string no arquivo e as imprime na tela

#include <stido.h>

int main(void)
{
   // Declarações
   FILE *ponteiro;
   char string[81];
   struct estrutura  acesso;
   // Instruções
   ponteiro =fopen("arquivo.bin","wb");
   while((strlen(gets(string))>0)
   {
      fputs(string, ponteiro);
      fputs("\n",ponteiro);
   }
   while(fgets(string, 80, ponteiro) != NULL)
           printf("%s",string);
   fclose(ponteiro);
   return 0;
}
 
 

A função getc() é um complemento da função putc() e ela lê um caractere por vez.

 

// Função que lê um caractere por vez do arquivo

#include <tido.h>

int main(void)
{
   // Declarações
   FILE *ponteiro;
   int caracter;
   struct dados acesso;
   // Instruções
   ponteiro = fopen("arquivo.txt","rt");
   while((caracter = getc(ponteiro)) != EOF)
         printf("%c",caracter);
   fclose(ponteiro);
   return 0;
}

 

Acesso Aleatório

 

O acesso aleatório permite acessar qualquer posição do arquivo sem necessitar acessar antes todas as posições intermediárias ou anteriores.

 

Ponteiros de Arquivos

 

Um ponteiro para um arquivo aponta para um byte específico denominado posição atual. A cada posição que é lida ou gravada no arquivo é movido o apontador interno para a próxima posição de leitura ou gravação dentro do arquivo. O apontador interno do arquivo aponta para o byte do próximo acesso (registro). Dessa forma, assim que o arquivo é aberto, o apontador interno é fixado no seu primeiro byte, permitindo a leitura ou gravação a partir do seu início. A abertura com a opção a (append), posiciona o ponteiro no fim do arquivo, ao invés do início.

 

A função fseek()

 

A função fseek() permite a movimentação do apontador interno do arquivo. Esta função é constituída por três argumentos. O primeiro é o ponteiro para a estrutura FILE do arquivo. Após a chamada da função fseek(), este ponteiro será movimentado para a posição que seja necessária dentro do próprio arquivo. O segundo argumento é chamado offset e consiste no número de bytes, a partir da posição especificada pelo terceiro argumento, de deslocamento para o ponteiro. É essencial que offset seja do tipo long int.

 

O último argumento é chamado modo. Existem três possibilidades para este modo que determina de onde o offset começará a ser usado (medido).

 
Modo Medido a partir de: Macro
0 Começo do Arquivo SEEK_SET
1 Posição Corrente do Arquivo SEEK_CUR
2 Fim do Arquivo SEEK_END

 

A função ftell()

 

Essa função retorna a posição do ponteiro de um arquivo binário em relação ao seu começo. Ela aceita um único argumento, que é o ponteiro para a estrutura FILE do seu arquivo e retorna um valor do tipo long int que representa o começo do arquivo até a posição atual. Pode ocorrer da função ftell() não retornar um número exato de bytes se for usada com arquivos em modo texto. Nesse caso ela é representada por um único caractere em C.

 

Condições de Erro

 

Funções como ferror() e perror() são utilizadas para informar que algum erro ocorreu durante a execução do programa. No primeiro caso o argumento que esta função aceita é um ponteiro para FILE. A função ferror() irá retornar um 0 (zero), se nenhum erro ocorreu e qualquer valor diferente de zero, se houver erro. Já a perror() é utilizada em conjunto com a ferror() e tem como argumento uma string fornecida pelo programa que normalmente é uma mensagem de erro indicando a parte do programa onde ocorreu o erro.

 

Exemplo

 

// Função que utiliza as duas funções citadas anteriormente para erro e 
// grava dados formatados no arquivo, incluindo funções de manuseio de erros

#include <stido.h>
int main(void)
{
   // Declarações
     FILE *ponteiro;
     double preco;
     char titulo[30];
     int regNum;
   // Instruções
    if(ponteiro = fopen("arquivo.txt","w") ==NULL))
    {
         printf("\n O arquivo nao pode ser aberto!");
         system("PAUSE");
         exit(1);
    }
    do{
        printf("\nDigite titulo, registro e preço: ");
        scanf("%s %d %f", titulo,&regNum, &preço);
        if(ferror(ponteiro != 0))     // Verifica erro imediatamente
        {
            perror("Erro de gravação:");
            fclose(ponteiro);
            exit(1);
        }
        fprintf("PONTEIRO,"%s %d %f",titulo, regNum, preco);
    } while(strlen(titulo) > 1);
    fclose(ponteiro);
    return 0;
}
 
 

A função ferror() e perror() aliadas imprimirá o resultado específico referente ao erro detectado, caso este ocorra.

 

A primeira parte da mensagem é fornecida pelo programa, e a segunda parte, pelo sistema operacional.

 

Técnicas de manipulaçã o de Arquivo

 

Exemplo:

 

/*
  Síntese
      Objetivo:Cadastrar dados no arquivo com uma chave seqüencial.
      Entrada:Dados do cadastro.
      Saída: Dados que irão ser gravados no arquivo
 
*/

#include <stdio.h>
#include <stdlib.h>
 
    typedef struct  
  {
      int codProduto;
      char nomeProduto[20];
      char descricao[60];
      float preco;
  } Produto;      // novo tipo de dado 
 
void cadastroProdutos()
{
   // Declarações
   FILE *p_arqIn,*p_arqOut;
   produto cadastra,compara;
   int cod=1;
   // Instruções
   // definindo código
    if( (p_arqOut = fopen( "cadastroProduto.bin","rb")) == NULL) // se o arquivo não
      printf ("Primeiro cadastro.");     // existir será o primeiro
   else
   {
      fseek(p_arqOut,-sizeof(produto),SEEK_END); 
      if((fread(&compara,sizeof(produto),1,p_arqOut)==1))
      { 
          cod = compara.codProduto;; //A LEITURA DO ULTIMO REGISTRO É FEITA
          cod++; //É ACRESCENTADO 1 AO VALOR DO ULTIMO REGISTRO
      }
      if ((fclose(p_arqOut))!=0)
           printf("O ARQUIVO NAO PODE SER FECHADO",1);
   
   }
   fflush(stdin);
  
   // CADASTRANDO OS DADOS
  
   puts("Informe o nome do produto");
   gets(cadastra.nomeProduto);
   puts("descricao:");
   gets(cadastra.descricao);
   fflush(stdin);
   printf("Informe o preço do produto: R$");
   scanf("%f",&cadastra.preco);
   fflush(stdin);
   clrscr();
   cadastra.codProduto = cod;
   printf ("Codigo: %d\n", cadastra.codProduto);
   printf ("Preco: R$%.2f\n", cadastra.preco);
   printf ("Nome: %s\n", cadastra.nomeProduto);
   printf ("Descricao: %s\n", cadastra.descricao);
   p_arqIn=fopen("cadastroProduto.bin","a+b"); //ABRINDO ARQUIVO
   fwrite(&cadastra,sizeof(produto),1,p_arqIn); //GRAVANDO DADOS
   fclose(p_arqIn); //FECHANDO O ARQUIVO
   fflush(stdin);
   getch();
}
 

Exclusão e Busca nos Registros

 

Continuando com o Exemplos com Produtos

 
/*
    Objetivo: Excluir registro do arquivo
    Entrada:Código do registro a ser excluído.
    Saída: Mensagem de erro o sucesso na execução do comando.
 
*/

void excluiProduto()
{
// Declarações
    FILE *p_arqOut;
    FILE *p_arqNovo;
    produto compara;
    int codProd;
    int existe=0; //flag de controle 
// Instruções  
    puts("Informe o codigo do Produto a ser excluido");
    scanf("%d",&codProd); //O CODIGO É INFORMADO PARA BUSCA
      if( (p_arqOut=fopen("produtos.bin","rb"))==NULL)//ABRINDO 
   {                                                                                         
//ARQUIVO ORIGINAL
       printf("O arquivo não pode se aberto");
       getch();
       exit(0);
   }
   if((p_arqNovo=fopen("Temp.bin","w+b"))==NULL) //ABRINDO ARQUIVO
   {                                                                                   
//TEMPORARIO
       printf("O arquivo não pode se aberto");
       getch();
       exit(0);
   }
   while(EOF != feof(p_arqOut))  // BUSCA REGISTRO EXISTENTE
   {  
         fread(&compara,sizeof(produto),1,p_arqOut);
         if(compara.codProduto==codProd)
             existe = 1;
   }  
   if(existe == 1) // SE O REGISTRO EXISTE…
   {
      rewind(p_arqOut);  // RETORNA O APONTADOR DO ARQUIVO 
 
 // COPIA TODOS OS REGISTROS DO ARQUIVO ORIGINAL, COM
 // EXCEÇÃO DO REGISTRO A SER EXCLUIDO, NO ARQUIVO
 // TEMPORARIO
       while(EOF !=feof(p_arqOut))
       {
          fread(&compara,sizeof(produto),1,p_arqOut);
          if(compara.codProduto!=codProd)
              fwrite(&compara,sizeof(produto),1,p_arqNovo);
       }
      //FECHANDO OS ARQUIVOS
      fclose(p_arqOut);
      fclose(p_arqNovo);
      //REMOVENDO O ARQUIVO ANTIGO
      remove("produtos.bin");
      //RENOMEANDO O ARQUIVO TEMPORARIO
      rename("Temp.bin","produtos.bin");
      printf("Exclusão realizada com sucesso\n");
      system("PAUSE");
   }
   else
   {
      printf("Registro não encontrado.\n");
      system("PAUSE");
   }
}
 

Alterando os Dados de Registros no Arquivo

 

/*
   Objetivo: Alterar registro do Produto
   Entrada: Codigo do Produto e novos dados.
   Saida: Mensagem de erro ou de sucesso na escrita no arquivo
*/

#include <stdio.h>
#include <stdlib.h>
void alteraProduto()
{
// Declaraçoes 
    FILE *p_arqOut;
    produto consulta;
    int cod,existe,local;
 // Instruçoes    
     clrscr();
     existe=0;               
     if( ( p_arqOut=fopen("produtos.bin","r+b"))!=NULL)
     {
         do{      
            printf("Informe o codigo do produtos para consulta:");
            scanf("%d",&cod);
         }while(cod<1);
         local=ftell(p_arqOut);
         fseek(p_arqOut,local-sizeof(produto),SEEK_SET);
         while(EOF != feof(p_arqOut))
         {
           if(fread(&consulta,sizeof(produto),1,p_arqOut)==1) //Verificando se 
           {                                                    //registro existe   
               if(consulta.codProduto==cod)
              {
                  existe=1;
                  break;
              }
           }
         }
         if(0 != existe)
         {
                puts("Registro nao encontrado");
                getch();
         }
         else
         {
              //Escrevendo os novos dados de registro
              do{
                 printf("Informe o novo nome:");
                 gets(consulta.nomeProduto);
             }while(strlen(consulta.nomeProduto)>18);
             do{
                 printf("\nInforme a nova descricao do produto:");
                 gets(consulta.descricao);
             }while(strlen(consulta.descricao)>58); 
             do{
                 printf("\nInforme o novo preco do produto");
                 scanf("%f",&consulta.preco);                             
             }while(consulta.preco<1);  
              //Voltando uma posição o  apontador do arquivo
             fseek(p_arqOut,-sizeof(produto),1);  
             //Escrevendo no arquivo
       if(fwrite(&consulta,sizeof(produto),1,p_arqOut) == 1)                       
              printf("\nArquivo alterado com sucesso");
                  else
                  printf("Erro na escrita no arquivo");     
             fclose(p_arqOut); //Fechando o arquivo
         }
     }
   }
   else
   {
         puts("Arquivo nao pode ser aberto!");
         getch(); 
   }
}
 
Com intuito de fixar a aprendizagem sobre Arquivo, sugere-se verificar o exemplo para ajudar no entendimento e aperfeiçoamento deste conteúdo.





Atividade de Fixação

 

No intuito de fixar a aprendizagem iniciada por meio deste módulo e verificar como está sua compreensão sobre o mesmo, são sugeridos alguns exercícios de fixação para serem resolvidos. Clique no link de exercícios ao lado, pois será por meio dele iniciada a lista de exercícios sobre os conteúdos estudados até este momento. Boa revisão sobre os mesmos!!