UFRJ-CCMN-INSTITUTO DE MATEMÁTICA
Departamento de Ciência da Computação


ARQUIVOS EM PASCAL  - Prof. Miguel Jonathan

Este texto apresenta alguns exemplos que esclarecem o uso de arquivos em Pascal.

1. Arquivos texto:
    São arquivos que contêm strings e caracteres.. O formato é uma sequência de caracteres separados por marcas de fim-de-linha.
   O exemplo abaixo permite ler linhas do teclado (texto) de tamanhos variados, para um arquivo de nome escolhido pelo usuário.
   O arquivo é sempre re-criado com
rewrite(f) e o texto é gravado caractere a caractere. A tecla ENTER gera um caractere de fim-de-linha, que é inserido normalmente no texto gravado. O laço de repetição interromperá quando for lido e gravado o caractere de numero 26 na tabela de caracteres ASCII, representado em Pascal por #26, que é uma forma equivalente a chr(26).
   Depois d egravado, o arquivo é reaberto, desta vez para leitura não-destrutiva com
reset(f), e agora o arquivo é lido linha a linha, usando o procedimento readln(f,s)dentro de um laço de repetição controlado pela função eof(f). Essa função retorna true somente após ser lido o último caractere.

program textos;
  var
    nome_arq: string;
    f:text;
    c:char;
    s: string;
  begin
   writeln ('Digite o nome do arquivo a criar');
   readln(nome_arq);
   writeln('Digite seu texto para ser gravado no arquivo ', nome_arq);
   writeln ('Termine com CTRL-Z seguido de ENTER');writeln;
   assign (f, nome_arq);
   rewrite(f);
   repeat
    read(c);
    write(f,c)
   until c=#26; {equivale a chr(26), que e' CTRL-Z}
   close(f);
   writeln('Agora observe o arquivo ', nome_arq, ' no seu diretorio');
   writeln;
   writeln ('Lendo agora do disco linha a linha e colocando na tela:");
   reset(f);  {abrindo para leitura}
   while (not eof(f)) do
    begin
    readln(f,s);
    writeln(s);
   end;
 end.

2. Arquivos formatados:
    São arquivos que contém texto representando números e/ou caracteres, representados no formato usado para entrada de dados pelo teclado com
read() e readln(). Não é a forma mais eficiente de gravar números (em binário ocupa bem menos espaço) mas em muitos casos pode ser de utilidade.
   No exemplo abaixo, é gravado no arquivo
arqtest.dat 30 reais gerados aleatoriamente entre 0 e 6900/7. (A função random(n)exige argumento inteiro, para gerar um número aleatório entre 0 e n. A divisão por 7 é para gerar um real.). Como é greado com writeln(f, ...) o efeito é colocar no arquivo uma imagem do seria impresso na tela com apenas writeln(...) , ou seja, os caracteres correspondentes à representação dos números no formato escolhido (8 colunas, com 2 casas decimais). Depois o arquivo é reiniciado para leitura, e os números são lidos do arquivo exatamente como seriam do teclado se fossem digitados nesse formato. A função eof(f)também retorna true após o úlitmo número ter sido lido do arquivo. Assim como no teclado, a leitura ignora espaços entre os números.

program p;
uses crt;
{testa arquivos de reais}
var
  f: text;
  x: real;
  i:integer;
begin
  clrscr;
  randomize;
  assign(f, 'arqtest.dat');
  rewrite(f);
  for i:=1 to 30 do write(f, random(6900)/7:8:2);
  reset(f);
  while not eof(f) do
  begin
    read(f,x);
    write(x:8:2); {mostra na tela}
  end;
  readln;
end.

3. Arquivos de registros:
     Neste exemplo, são gravados em forma binária uma sequência de elementos de um determinado tipo. Esse tipo pode ser qualquer tipo básico da linguagem, como integer, real, char, boolean, ou um tipo definido pelo programador, com um record ou um array. Nesse caso não há separadores de linha, e a leitura e gravação são feitas com uso dos procedimentos
read(f,...) e write(f,...) não sendo permitido usar readln() e writeln().
    No exemplo, é definidos um tipo de registro,
rec para nomes.dat.  Os registros associam uma "chave", o número de inscrição DRE do aluno, ao seu nome. . O arquivos é definido como sendo file of rec1.
    Esse programa é um pouco mais elaborado. Ele permite que o mesmo programa seja usado tanto no caso do arquivo não existir, como no caso de já existir. Para isso, o programa usa um artifício, que é a "diretiva de compilação"
{$I-}. Diretivas de compilação orientam o compilador a gerar programas objeto com características especiais. Elas sempre têm a forma de um comentário entre chaves, contendo um cifrão seguido de uma letra e o sinal - ou +. A letra indica a diretiva, nocao I indica "entrada e saída". O sinal - indica que a partir desse ponto o programa "desliga" a sua capacidade de abortar em caso de ocorrer um erro de entrada ou saida de dados. A partir da linha seguinte a {$I+} essa capacidade de abortar volta a funcionar.
    O truque aqui é tentar ler um arquivo que ainda não pode não existir ainda, com
reset(f1). Se ele não existir, dará erro de entrada/saida, mas o programa não abortará, por causa da diretiva. Em vez disso, o efeito será tornar uma variável especial do Pascal, de nome IOResult com um valor diferente de zero, ou zero se não tiver havido erro. Essa variável é testada, e se for diferente de zero, então se usa rewrite(f1) sem perigo. Em qualquer dos casos, a função seek(f1, n)  é usada para posicionar o arquivo para gravar após o último registro. Essa função posiciona o arquivo no registro n, no caso será filesize(f1), que dá o número de registros do arquivo. Se for um arquivo novo, n=0, e seek(f1,0) equivale a reset(f1). Portanto o mesmo programa pode ser usado para criar o arquivo, ou adicioanr registros ao arquivo se já existir, sem que o usuário tenha que se preocupar com isso.
   O programa pede para o usuário entrar com dados pelo teclado, e ir gravando, em um laço controlados pela função
eof(f1). Essa função deve retornar true quando chegar ao fim do arquivo, e nesse caso o arquivo de entrada é o próprio tecaldo. O sinal de fim de arquivo do teclado é dado quando se tecla CTRL-Z.
   Depois de gravar os registros, o arquivo é reiniciado com
reset(f1)e seus dados são lidos para um vetor vet1 de registros do mesmo tipo rec1.. O vetor é então ordenado pelo campo de DRE, usando um algoritmo simples de ordenação por seleção, e os registros são regravados e listados na tela em ordem de DRE.
 

program arquivo1;
(****************************************************************
 Este programa cria um arquivo nomes.dat no diretorio corrente.
 Caso o arquivo nao exista, ele sera' criado, caso ja' exista
 será aberto, e os registros trazidos para o vetor vet1.
 O programa pede para incluir registros contendo o DRE e o nome
 de alunos, um em cada linha. Terminar com CTRL-Z (fim de arquivo
 pelo teclado). O vetor é entao ordenado pelo campo DRE, e o
 arquivo e' totalmente re-gravado com o conteudo do vetor.
 A seguir o arquivo e' reaberto para leitura com reset(), e cada
 registro e' lido e seus campos impressos na tela.
 ATENCAO: este programa nao funcionara' se a unit CRT for usada,
 pois nesse caso CTRL-Z nao mais sera' equivalente a um fim de
 arquivo.
 Versao corrigida em 12/3/2002. O algoritmo de ordenacao por
 selecao continha um erro na versao anterior.
*****************************************************************)
 type rec1 =
         record
         dre: string;
         nome: string;
         end;
 
  var
  f1: file of rec1;
  r1, temp: rec1;
  vet1: array [1..50] of rec1;
  i,j, posmenor,n1: integer;

  begin
     assign(f1, 'nomes.dat');
    {$I-}
    reset(f1);
    if IOResult <> 0 then rewrite(f1);
    seek(f1, filesize(f1));   {posiciona-se no fim do arquivo}
    {$I+}

    writeln('Digite novos registros do arquivo na forma:');
    writeln('    DRE');
    writeln('    NOME');
    while not eof(input) do
      with r1 do
        begin
         readln (dre);
         readln(nome);
         write(f1,r1);
        end;
    close (f1);

    { Lendo o conteudo de f1 para o vetor vet1 na memoria ...}
    reset (f1);
    n1:= 0;
    while not eof(f1) and (n1 < 50) do
     begin
      n1:=n1+1;
      read (f1, vet1 [n1] );
     end;   { vet1 vai conter os n1 registros do arquivo f1}

    {ordenando f1...pelo algoritmo de selecao}
    for i:=1 to n1 do
     begin
      posmenor:= i;
      for j:=i+1 to n1 do
        if vet1[j].dre < vet1[posmenor].dre then posmenor:=j;
      if posmenor<> i then
        begin
        temp:=vet1[i];
        vet1[i]:=vet1[posmenor];
        vet1[posmenor]:= temp;
        end;
     end;
 
     {re-gravando os registros ordenados em f1...}
     rewrite(f1); i:= 0;
     for i:= 1 to n1 do write (f1, vet1[i]);

    {lendo e imprimindo na tela o conteudo de f1...}
   
reset(f1);
    while not eof(f1) do
     begin
      read(f1,r1) ;
      with r1 do  writeln (dre,'':3,nome);
     end;
    writeln;
    close(f1);
  end.