ASIX-M10-UF2. Emmagatzematge en fitxers I: fitxers plans

De wikijoan
Salta a la navegació Salta a la cerca

Introducció

En aquesta pràctica estudiarem les operacions bàsiques d'accés a fitxers (selecció, modificació, inserció i esborrat) amb una aplicació escrita amb llenguatge C. Sense pretendre que l'alumne entengui la totalitat del codi, sí que es pretén que l'alumne prengui consciència de la importància dels punters o buffers de memòria en aquestes aplicacions de baix nivell.

Descàrrega

Desenvolupament

Tenim una base de dades textual, representada pel fitxer municipis.txt, que consta del següent format:

id;municipi;comarca;provincia

Per exemple:

...
225;Cornudella de Montsant;Priorat;Tarragona
226;Creixell;Tarragonès;Tarragona
227;Crespià;Pla de l'Estany;Girona
...

El professor explicarà la generació d'aquest fitxer a partir de les dades obtingudes a:

Volem realitzar un programa que accedeixi al contingut d'aquest fitxer i pugui fer les operacions bàsiques sobre fitxers:

  • consulta
  • consulta amb filtre
  • modificació d'un registre
  • inserció d'un registre
  • eliminació d'un registre.

Es proporciona el programa municipis_catalunya.c. Aquest programa està en fase preliminar, i consta de diversos bugs que s'aniran corregint. De totes maneres, és interessant veure el codi per adonar-se de com les operacions bàsiques de fitxers implica la lectura seqüencial del fitxer; volcar el contingut del fitxer en un buffer de memòria; funcions diverses sobre el buffer de memòria; funcions diverses de tractament de cadenes. Tot plegat no és fàcil d'entendre i de programar.

La programació a baix nivell amb llenguatge C (accedint directament als buffers de memòria) és la tria correcte per fer un programa d'aquest tipus. Les aplicacions comercials i d'usuari utiliitzen altres llenguatges d'alt nivell i amb interfície d'usuari (JAVA, PHP, ...). Però utilitzar el llenguatge C per fer aquest programa és l'aproximació correcta.

Per compilar aquest programa i obtenir-ne el binari executable, necessitaràs les eines de compilació bàsiques (el compilador gcc). En sistemes basats en Debian/Ubuntu les trobaràs instal.lant el paquet build-essential:

$ sudo apt-get install build-essential

Per compilar l'aplicació:

$ gcc municipis_catalunya-1.0.c -o municipis_catalunya

I per executar-la:

$ ./municipis_catalunya

Aleshores accedeixes al menú i pots realitzar les diferents operacions sobre el fitxer. Quan es fa una operació de inserció i esborrat, s'hauria de fer una reindexació dels index de manera que siguin correlatius, des del 1 fins al final. (aquesta part està per fer).

Altres millores que es podrien fer al programa serien: modificar l'ordre dels registres (moure els registres a una posició diferent); ordenar els registres per diferents criteris (ordre alfabètic de municipis, ...); filtrar registres amb dos o més criteris (per ex...). El programa que es presenta només pretén mostrar les operacions bàsiques.

video

Perseguint la integritat

De l'any passat ja saps que els SGBD relacionals tenen claus primàries i forànies, i això ens permet tenir integritat referencial, que implica no cometre errors. Anem a veure com es podria implementar un sistema bàsic d'integritat referencial basat en fitxers.

Fixem-nos que una província té moltes comarques, i que una comarca té molts municipis. Tal com està dissenyada la base de dades textual, quantes vegades apareix la paraula 'Tarragona'? Moltes. Això pot induir errors, per exemple, en algun registre es pot posar 'Tarragnoa' en comptes de 'Tarragona', i aquest registre quedaria invalidat. És per això que es van inventar els index. Una implementació de tres fitxers amb tres index de la nostra base de dades seria similar a:

Fitxer PROVINCIA
-----------------
1;Barcelona
2;Tarragona
3;Lleida
4;Girona


Fitxer COMARCA
---------------
1;Baix Camp;2
2;Berguedà;1
3;Pallars Sobirà;3
4;Anoia;1
...

MUNICIPI
--------------
1;El Vendrell;1
2;Cubelles;1
3;Berga;2
4;Bagà;2
5;Esterri d'Àneu;3
6;Sort;3
7;Igualada;4
8;Òdena;4
...

Si ens fixem bé amb aquests tres fitxers té sentit preguntar-se:

  • Quins són els municipis de Lleida?
  • Quines són les comarques de Tarragona que tenen més de 25 municipis?
  • etc.

Però implementar una segona versió de la nostra aplicació que contempli la lectura i escriptura sobre els tres fitxers, fa que la nostrra aplicació, que la volíem simple, passi a ser més complicada. Si en aquesta segona versió volguéssim trobar els municipis de Girona, més o menys el procés seria el següent:

  • primer buscaríem l'índex de Girona en el fitxer PROVINCIA: és el 4
  • posaríem en un buffer (una estructura de memòria) tots els index de les comarques que pertanyen a Girona, llegint el fitxer COMARCA.
  • Ara ja podem llegir el fitxer MUNICIPI i cerquem tots els municipis amb alguna comarca de Girona.

Resulta evident que les bases de dades relacionals que vas estudiar l'any passat (l'ús de taules i camps), i el llenguatge SQL ofereix moltes avantatges. És per això que no s'utiltizen les bases de dades textuals quan les dades estan relacionades. Però en determinats casos sí que pot ser suficient una implementació com la que hem fet, com el cas pràctic que mostrem a continuació.

Cas pràctic: Joanillo Arcade Frontend

El projecte Pimame/Piplay és un emulador dels jocs Arcade de tota la vida, basat en el projecte MAME, que s'ha portat al hardware Raspberry Pi. En aquest cas es tractava de programar un front-end que permeti llençar els diferents jocs, classificats per categoria i jugabilitat. El front-end llegeix el fitxer romlist.txt:

...
1941\tCounter Attack\tVery good\tShooter
1942\tCounter Attack 1942\tPrefered\tShooter
1943kai\tThe battle of Midway\tVery good\tShooter
aafb\tAll American Footb\tBad\tSports
abaseb\tAtari Baseball\tBad\tSports
actfancr\tactfancr\tGood\tFP-Shooter
aerofgt\tAero Fighters\tPrefered\tShooter
...

que consta de 4 camps separats per tabulador: el nom de la rom, el nom del joc, classificació de jugabilitat i classificació de categoria del joc. L'aplicació fa una lectura d'aquest fitxer i pots filtrar els jocs, per exemple: Shooter i Very good. En aquest cas no quedaria justificat sota cap concepte instal.lar un sistema gestor de bases de dades com ara MySQL per per aquesta tasca.

Format dBase (dbf)

L'aplicatiu dBase i el format dbf eren molt populars els anys 80 i 90. Quan les botigues es van començar a informatitzar, les aplicacions de clients, stock, facturació, etc., anaven amb dBase (cerca a Google Images per dBase).

Tenim el fitxer clientes.dbf, que emmagatzema informació de clients en format dbf. Tot i que el fitxer és binari, podem veure la informació que conté si el visualitzem per exemple amb cat, o millor un editor hexadecimal (per ex ghex), amb el qual, a part de llegir, podrem modificar el seu contingut.

També el podem mirar d'obrir amb un full de càlcul com el Openoffice Calc (o el Excel).

$ sudo apt-get install ghex

Fitxer:Clientes.zip

Llegir fitxers amb Python

En administració de sistemes cada vegada s'està utilitzant més i més el llenguatge Python. Veiem amb aquest senzill codi com podem fer una lectura seqüencial del fitxer municipis.txt amb Python.

$ joe reader.py
import fileinput

content = []
for line in fileinput.input():
    content.append(line.strip())

fileinput.close()
print (content)

Per executar-lo:

$ python3 reader.py municipis.txt

NOTA: se suposa que l'alumne té instal·lat el Python3

Llegir fitxers amb Perl

$ joe reader.pl

use strict;
use warnings;
     
my $filename = 'municipis.txt';
open(my $fh, '<:encoding(UTF-8)', $filename)
or die "Could not open file '$filename' $!";
     
while (my $row = <$fh>) {
chomp $row;
print "$row\
";
}

Per executar-lo:

$ perl reader.pl

Llegir fitxers amb Bash

script reader.sh:

#!/bin/bash
filename='municipis.txt'
echo Start
while read p; do 
    echo $p
done < $filename
$ bash reader.sh
o bé
$ ./reader.sh

Llegir fitxers amb PHP (CLI)

CLI significa command line interface, és a dir, el PHP es pot executar des de la consola, com a llenguatge de script:

$ sudo apt-get install php-cli

script reader.php:

<?php
  $fn = fopen("municipis.txt","r");
  
  while(! feof($fn))  {
\t$result = fgets($fn);
\techo $result;
  }

  fclose($fn);
?>
$ php reader.php

Conclusió

Hem vist que amb diferents llenguatges (compilats o interpretats) és molt fàcil llegir seqüencialment un fitxer. Però quan volem fer operacions ràpides de lectura/escriptura sobre fitxers no hem de treballar de forma seqüencial i línia a línia, sinó que hem de treballar amb blocs de memòria (buffer), que residiran a la RAM (les operacions a la RAM sempres seran molt més ràpides). Per això necessitem llenguatges de programació que treballin a baix nivell com el C o C++. És per això que el MySQL (com a servei) ha estat programat amb un llenguatge de baix nivell com el C o C++.

Entrega

Els alumnes entregaran al Google Classroom tots els fitxers generats. S'empaquetaran tots aquests fitxers i es pujaran al Google Classroom dins del termini d'entrega de la pràctica.

Recorda la normativa per entregar les pràctiques al Google Classroom: ASIX-M10-UF2#Normativa_d.27entrega_de_les_pr.C3.A0ctiques_al_Google_Classroom

Guió de l'entrega

S'entregarà amb un pdf, que inclourà les captures de pantalla, els exercicis segons el següent guió:

1. Nom i cognoms, data

2. Comentaris sobre la pràctica (llegeix-me)

3. Compilar i executar municipis_catalunya-1.0.c

4. Mirar i estudiar el codi. Detectar els blocs funcionals: 
-on es printa el menú?
-quin és el punt d'entrada de l'aplicació
-on s'executen les funcions quan escollim una opció del menú (1 a 6 opcions)

5. Fitxers PROVINCIA, COMARCA, MUNICIPI
-Com serien els fitxers PROVINCIA, COMARCA, MUNICIPI si només ens interessés els municipis del Baix Camp?
-Explica com faries un algorisme per buscar els municipis que comencen per 'B' de la província de Girona.

6. Format dBase (dbf)
-cerca a Internet una imatge dels anys 80 d'una aplicació de gestio empresarial que accedeix a una base de dades en format dBase III o dBase IV (pantalla blava).
-cerca un fitxer dbf i obre'l amb un editor de text pla. Quin tipus d'informació pots identificar dins d'aquest fitxer?

7. Python: reader.py

8. Perl: reader.pl

9. Bash: llegir.sh
 
10. PHP: reader.php

11. Ampliacions, comentaris, etc.



creat per Joan Quintana Compte, setembre 2019