Baixe o app para aproveitar ainda mais
Prévia do material em texto
Módulo 7 Tratamento de Ficheiros PSI 1º ano 2018/2019 TGPSI - Paulo Reis - Agrupamento de Escolas da Batalha 2 Tratamento de Ficheiros - Parte 4 - 3 Ficheiros de Texto (Revisão) Um ficheiro de texto não é mais do que uma sequência de carateres que ficam armazenados no disco do computador. Essa sequência de carateres é terminada com um carater especial denominado fim-de-ficheiro (EOF). 4 Limitações dos Ficheiros de Texto Os ficheiros de texto apenas dão resposta a uma forma de manipulação de informação muito específica, no formato de sequências de carateres que, na melhor das hipóteses, se encontram separados por carateres de fim- de-linha. O acesso a estes ficheiros é feito de forma sequencial, ou seja, torna necessário percorrer o ficheiro à procura da informação pretendida. Quando os nossos dados não se encontram neste formato, é necessário recorrer ao ficheiros binários, que entre outras vantagens permitem o acesso direto aos dados. 5 Linguagem C Ficheiros Binários 6 Ficheiros Binários Os ficheiros binários estão organizados em elementos de dimensão fixa que podem ser de tipos simples ou registos (estruturas). Assim, nos ficheiros binários não há marcas de “fim de elemento”, porque o fim de cada elemento é sempre conhecido. Modos de acesso: Modo de acesso sequencial: os elementos do ficheiro são acedidos sequencialmente, em posições consecutivas. Modo de acesso aleatório ou direto: os elementos do ficheiro, necessariamente de dimensão fixa, são acedidos por qualquer ordem. 7 Ficheiros Binários VS. Ficheiros de Texto Os ficheiros binários costumam usar-se quando temos grandes quantidades de dados que necessitam de ser tratados rapidamente em acesso direto e sofrem contínuas alterações, não sendo prático estarmos a basearmo-nos em cópias do ficheiro. Os ficheiros de texto são muito confortáveis de utilizar visto poderem ser editados e inspecionados com qualquer dos muitos editores de texto disponíveis. Contudo, só devem ser usados quando os dados armazenados sofrem poucas alterações e a sua quantidade é moderada. Utilização: 8 Ficheiros Binários VS. Ficheiros de Texto Os ficheiros binários geralmente têm tempos de leitura e escrita mais rápidos que os ficheiros de texto, já que uma imagem binária do registo é armazenada diretamente da memória para o disco (ou vice-versa). Num ficheiro de texto, tudo precisa ser convertido de trás para frente em texto e este processo consome tempo. Acesso: 9 Operações com ficheiros 10 Abertura de Ficheiros Binários A abertura de um ficheiro binário é feita de forma semelhante aos ficheiros de texto , bastando acrescentar a letra ‘b’ ao modo de abertura. fp = fopen("dados.bin", "rb"); Modos de acesso para ficheiros binários rb Abre o ficheiro para leitura wb Abre o ficheiro para escrita (cria ficheiro se inexistente) ab Abre o ficheiro para adição de conteúdo no final do ficheiro r+b Abre o ficheiro para leitura e escrita, coloca o apontador no início w+b Abre o ficheiro para escrita em sobreposição com o conteúdo existente a+b Abre o ficheiro para leitura e escrita, adiciona conteúdo no final do ficheiro caso este exista 11 Modos de acesso Modos de acesso r Abre o ficheiro de texto para leitura w Abre o ficheiro de texto para escrita (cria ficheiro se inexistente) a Abre o ficheiro de texto para adição de conteúdo no final do ficheiro r+ Abre o ficheiro de texto para leitura e escrita, coloca o ponteiro no início w+ Abre o ficheiro de texto para escrita em sobreposição com o conteúdo existente a+ Abre o ficheiro de texto para leitura e escrita, adiciona conteúdo no final do ficheiro caso este exista rb abre o ficheiro binário para leitura wb Abre o ficheiro binário para escrita (cria ficheiro se inexistente) ab Abre o ficheiro binário para adição de conteúdo no final do ficheiro r+b Abre o ficheiro binário para leitura e escrita, coloca o apontador no início w+b Abre o ficheiro binário para escrita em sobreposição com o conteúdo existente a+b Abre o ficheiro binário para leitura e escrita, adiciona conteúdo no final do ficheiro caso este exista 12 Escrita em Ficheiros Binários A função fwrite() transfere um bloco de dados, com um determinado tamanho em bytes, da memória primária para o ficheiro. int fwrite(const void *ptr, int size, int n, FILE *fp) const void *ptr é um apontador para qualquer tipo de dados e irá conter o endereço de memória do bloco de dados que pretendemos escrever no ficheiro; int size indica o tamanho em bytes de cada um dos elementos que vamos escrever; int n representa o número de elementos a escrever; FILE *fp indica o ficheiro de dados onde pretendemos realizar a operação de escrita. 13 fwrite() Protótipo: int fwrite(const void *ptr, int size, int n, FILE *fp) O valor de retorno da função fwrite() representa o número de elementos (dos n) que conseguiu escrever com sucesso. 14 fichBinario01.c Código-exemplo 15 Código-exemplo fichBinario02.c 16 Leitura de Ficheiros Binários A função fread() lê um bloco de dados, com um determinado tamanho em bytes, do ficheiro para a memória primária. int fread(const void *ptr, int size, int n, FILE *fp) const void *ptr é um apontador para qualquer tipo de dados e irá conter o endereço de memória do bloco de dados que pretendemos ler do ficheiro; int size indica o tamanho em bytes de cada um dos elementos que vamos ler; int n representa o número de elementos a ler; FILE *fp indica o ficheiro de dados onde pretendemos realizar a operação de leitura. 17 fread() Protótipo: int fread(const void *ptr, int size, int n, FILE *fp) O valor de retorno da função fread() representa o número de elementos (dos n) que conseguiu ler com sucesso. 18 fichBinario03.c Código-exemplo 19 Ficheiros Binários e Estruturas A linguagem C suporta o conceito de ficheiro de estruturas de forma básica. Ao abrir o ficheiro, podemos ler uma estrutura, escrever uma estrutura ou pesquisar qualquer estrutura no arquivo. Este conceito de ficheiro suporta o conceito de um apontador de ficheiro. Quando o ficheiro é aberto, o apontador aponta para o registo 0 (o primeiro registo no ficheiro). Qualquer operação de leitura lê a estrutura apontada e desloca o apontador um nível abaixo na estrutura. Qualquer operação de escrita grava na estrutura apontada e move o apontador um nível abaixo na estrutura. Um processo de Seek move o apontador para o registo solicitado. 20 Acesso sequencial e acesso direto Acesso sequencial: percorre-se o ficheiro até localizarmos aquilo que pretendemos. Acesso direto: colocamo-nos na posição que queremos de um ficheiro, sem ter que percorrer todos os Bytes que se encontram antes dessa posição. 21 Posicionamento ao longo do ficheiro Sempre que se abre um ficheiro para leitura (“r“) ou escrita (“w”) ficamos posicionados na posição zero do ficheiro, isto é, imediatamente antes do primeiro Byte. Se o ficheiro for aberto para acrescento (“a”) ficamos posicionados a seguir ao último Byte do ficheiro. Só faz sentido falar em posicionamento em ficheiros quando estamos a processar ficheiros binários. ftell() – esta função indica qual a posição que ocupamos presentemente num ficheiro. rewind() – permite colocar o apontador a apontar para o início do ficheiro, independentemente da posição onde se encontra atualmente. 22 ftell() Protótipo: long ftell(FILE *fp) A função ftell() devolve um valor long e não int pois a dimensão de um ficheiro pode ultrapassar o valor máximo representado por um inteiro. Neste exemplo, a função ftell() devolve o número de Bytes que o ficheiro contém, pois estamos posicionados no final do ficheiro .Para saber quantos reais estão lá dentro, bastará dividir esse valor pelo tamanho de cada float. 23 rewind() Protótipo:void rewind(FILE *fp) O procedimento rewind() não devolve qualquer valor e é usado sempre que queremos regressar ao início de um ficheiro. 24 Acesso direto a Ficheiros Binários Os ficheiros binários são geralmente geridos em modo direto, isto é, acedendo diretamente a qualquer elemento dentro do ficheiro. A função fseek() permite modificar o apontador do ficheiro da forma pretendida. int fseek(FILE *fp, long salto, int origem) FILE *fp indica a variável de ficheiro de dados. long salto designa o valor em bytes que pretendemos "andar" quer para a frente quer para trás relativamente à origem. int origem indica a posição no ficheiro, podendo apresentar um de três valores possíveis. 25 fseek() Protótipo: int fseek(FILE *fp, long salto, int origem) O parâmetro origem tem três valores possíveis, representados pelas seguintes constantes simbólicas: SEEK_SET: início do ficheiro (0); SEEK_CUR: posição corrente do ficheiro (1); SEEK_END: fim do ficheiro (2). A função fseek() retorna zero se houve sucesso ou um valor diferente de zero se houve falha no posicionamento do apontador do ficheiro. 26 fichBinJunk.c Código-exemplo O programa exemplo grava e depois lê 10 registos num ficheiro binário de nome "junk.dat“. 27 Abre o ficheiro junk.dat para gravação e depois escreve dez os (10) registos. 28 Abre o ficheiro junk.dat para leitura e depois lê, sequencialmente e um a um, os registos criados anteriormente. 29 Abre o ficheiro junk.dat para leitura e depois lê os registos, um a um, em ordem inversa usando a função fseek(). 30 Abre o ficheiro junk.dat para leitura e depois lê os registos, desde o inicio do ficheiro e um a um, usando a função fseek(). 31 Abre o ficheiro junk.dat e usando a função fseek() lê o quarto registo, que altera e depois guarda no ficheiro. 32 Abre o ficheiro junk.dat, lê e exibe os registos para podermos verificar que o quarto registo foi realmente alterado. fichBinJunk.c 33 Neste programa, uma descrição de estrutura rec foi usada para definir um tipo Registo, mas podemos usar a descrição de uma outra estrutura qualquer (desde que devidamente codificada). Podemos verificar que as funções fopen() e fclose() trabalham exatamente da mesma forma que nos ficheiros de texto. As outras funções usadas são fread(), fwrite() e fseek(). A função fread() captura quatro parâmetros: • um endereço de memória; • o número de bytes a ser lido por bloco; • o número de blocos a ser lido; • a variável de ficheiro. Assim, a linha fread(&r, sizeof(Registo), 1, f); diz para ler 12 bytes (o tamanho da struct rec) do ficheiro f (a partir do local atual do apontador de ficheiro) no endereço de memória &r. O código explicado 34 Neste programa para cada registo um bloco de 12 bytes é solicitado. Seria facilmente posssível ler 100 blocos por disco numa matriz na memória alterando 1 para 100. A função fwrite() funciona da mesma forma que nos ficheiros de texto, mas aqui desloca o bloco de bytes da memória para o ficheiro. A função fseek() desloca o apontador do ficheiro para um byte no ficheiro. Em geral, mudamos o apontador em incrementos de sizeof(Registo) para manter o apontador nos limites do registo. Podemos usar três opções ao pesquisar: SEEK_SET, SEEK_CUR e SEEK_END. • SEEK_SET desloca o apontador x bytes para baixo, a partir do início do ficheiro (desde o byte 0 no ficheiro). • SEEK_CUR desloca o apontador x bytes para baixo da posição atual do apontador. • SEEK_END desloca o apontador do final do ficheiro (com esta opção precisamos de usar limites negativos). 35 Várias opções diferentes de abertura do ficheiro aparecem no código do programa. Observa em particular a seção na qual o ficheiro é aberto com o modo rb+. Isto abre o ficheiro para leitura e escrita, permitindo que os registos sejam alterados. No código é realizada um procura de um registo, lê e altera um campo. Depois procura novamente, pois a leitura deslocou o apontador, e guarda a alteração. 36 Quando um ficheiro é aberto, fica-se sempre posicionado na primeira posição do mesmo. Caso queiramos fazer uma leitura em outra posição, devemos posicionar-nos corretamente na mesma. Da mesma forma, se desejarmos gravar algum novo (dado ou registo), devemo-nos posicionar no final do ficheiro para que os dados existentes nele não sejam substituídos. Quando se lê ou grava de um ficheiro, automaticamente somos colocados na próxima posição do mesmo: próxima linha, num ficheiro de texto ou próximo registo, nos ficheiros-binários. Notas importantes Antes de ler ou gravar dados em ficheiro binários, é importante estar posicionado no local correto. 37 fichBinPlayers.c Código-exemplo O programa exemplo grava e depois altera um conjunto de registos num ficheiro binário “players.dat”. 38 39 40 fichBinPlayers.c Prontos para a ação de férias ?! 41 Hora de resolver… 42 1) Escrever um programa que leia um vetor com 10 inteiros a partir do teclado e guarde os seus valores num ficheiro binário com o nome Dados.dat. 2) Escrever um programa que carregue um vetor com 10 inteiros lidos a partir do ficheiro Dados.dat escritos em disco pelo programa anterior. Depois de ler os 10 inteiros deverá mostrá-los no ecrã. 3) Escrever um programa que abra um ficheiro binário indicado pelo utilizador e informe quantos Bytes este contém, obtendo este valor através de acesso sequencial. 4) Escrever um processo de introdução de dados pelo utilizador para o programa exemplo fichBinPlayers.c. 43 5) Escrever um programa que solicite ao utilizador um conjunto de 10 números reais, os armazene num ficheiro binário. Em seguida deve solicitar ao utilizador um número entre 1 e 10 e mostrar o valor que tinha sido introduzido nessa ordem. 6) Escrever e testar um programa que crie um ficheiro com registos de pessoal de uma empresa com campos de nome e salário. A leitura de dados termina quando se especifica ‘.’ como nome. Já enviasJá enviasJá enviasJá envias----te os te os te os te os ToDos?ToDos?ToDos?ToDos? Não?!! Vais levar uma Não?!! Vais levar uma Não?!! Vais levar uma Não?!! Vais levar uma “chumbada” no módulo.“chumbada” no módulo.“chumbada” no módulo.“chumbada” no módulo. Resumo das aulas de PSI …
Compartilhar