Informatica
ARCHIVI E FILE:
cancellazione di un record
Prof. Ciaschetti
La cancellazione di un record dall’archivio può essere di due tipi, logica o fisica.
-
Nella cancellazione logica, il record rimane fisicamente nel file, ma il suo contenuto
informativo non ha più alcun valore per l’archivio.
Nella cancellazione fisica, il record viene materialmente eliminato dall’archivio.
La cancellazione logica è molto veloce, soprattutto se è possibile accedere direttamente al record da
cancellare: si tratta, in buona sostanza, di effettuare una modifica di un apposito campo chiamato
cancellato, che indica se il record è stato cancellato oppure no (come un flag). La cancellazione
fisica invece è molto dispendiosa, e prevede la riscrittura di quasi l’intero archivio (tutto l’archivio
tranne il record da cancellare).
La soluzione più comunemente adottata prevede una combinazione di cancellazioni logiche e
fisiche come segue: quando si vuole cancellare un record si effettua una cancellazione logica. Solo
periodicamente si procederà a una compattazione del file, cancellando fisicamente tutti i record che
sono stati cancellati logicamente, cioè scandendo tutto il file e riscrivendo solo i record non
cancellati logicamente. Di seguito, è riportato il codice per effettuare la cancellazione logica
utilizzando un campo apposito.
Prese come esempio le seguenti strutture dati e variabili,
struct cane
{
char nome[20];
char razza[20];
int eta;
int cancellato;
};
typedef struct cane dog;
dog d;
FILE *fp;
Possiamo effettuare una cancellazione logica andando a modificare il campo cancellato, cioè
alzando il flag. Nel codice che segue, supponiamo di non conoscere a priori la posizione del record
da cancellare, e di dover effettuare quindi una ricerca del record.
char nome_da_cancellare[20];
printf(“quale cane vuoi cancellare? ”);
scanf(“%s”, nome_da_cancellare);
fp = fopen("canile.dat", "r+");
int trovato = 0;
while ((!trovato) && (!feof(fp)))
/* cerca il record da cancellare */
{
fread(&d, sizeof(dog), 1, fp);
if (!strcmp(d.nome, nome_da_cancellare))
{
trovato = 1;
d.cancellato = 1; /* alza il flag */
fseek(fp, -sizeof(dog), SEEK_CUR); /* riscrivi il record */
fwrite(&d, sizeof(dog), 1, fp);
}
}
fclose(fp);
E’ importante, al momento dell’inserimento di un nuovo record nell’archivio, ricordarsi di
inizializzare il campo cancellato a 0 per indicare che il record non è (logicamente) cancellato, e
considerare tale campo nelle ricerche: se un record è stato cancellato, anche se solo logicamente,
non dovrebbe essere più considerato.
Come dicevamo, quando si effettua la cancellazione logica in questo modo, occorre prevedere una
procedura di compattazione del file, che provveda a cancellare fisicamente i record che erano stati
cancellati logicamente. Questa procedura non verrà fatta partire ogni volta che si vuole cancellare
un record, ma solo ogni tanto, magari come processo da eseguire in background, quando il sistema
non è impegnato in altre operazioni. La procedura prevede di riscrivere su un secondo file tutti i
record tranne quelli cancellati logicamente, quindi eliminare il vecchio file e rinominare il nuovo
con il vecchio nome.
/* cancellazione fisica */
FILE *fp1, *fp2;
fp1 = fopen("canile.dat", "r"); /* archivio vecchio */
fp2 = fopen("canile2.dat", "w"); /* archivio nuovo */
while(!feof(fp1))
{
fread(&d, sizeof(dog), 1, fp); /* riscrivi sul nuovo archivio i
record non cancellati
logicamente */
if (!d.cancellato)
fwrite(&d, sizeof(dog), 1, fp2);
}
fclose(fp1);
fclose(fp2);
remove("canile.dat"); /* rimuovi il vecchio archivio */
rename("canile2.dat","canile.dat"); /* rinomina il nuovo archivio
come il vecchio */
NOTA: per includere la cancellazione nel progetto dell’archivio,
aggiungere due funzioni
1) Cancella (effettua la cancellazione logica)
2) Compatta archivio (effettua la cancellazione fisica)