Corso di Visual
Basic
Nella scorsa lezione sono
stati presi in considerazione i file di testo, in cui laccesso alle informazioni
avviene in modo sequenziale. Essi presentano un limite, ovvero la scarsa idoneità alla
memorizzazione di grandi quantità di dati, a causa dei talvolta elevati tempi di ricerca.
La soluzione dellesercizio proposto nella scorsa lezione Lesercizio proposto
nello scorso numero prevede la realizzazione di un programma in grado di leggere, per
mezzo di opportune textbox, tre valori numerici interi e una stringa, nonché di offrire
la possibilità di salvare questi dati su richiesta dellutente. La pressione di un
pulsante deve provocare il ripristino allinterno delle caselle di testo dei valori
salvati. Il codice è contenuto nel Listato 1. Lapplicazione è composta da
due procedure; la prima, associata alla pressione del pulsante btnSalva, ha lo
scopo di scrivere le informazioni sul file Archivio.dat. I file ad accesso casuale I file ad accesso casuale sono caratterizzati dallorganizzazione molto rigida in strutture dette record. Un file è quindi composto da un numero variabile di record accodati. Al fine di comprendere meglio il concetto, si pensi a uno schedario, quale ad esempio lanagrafica dei clienti di unazienda. Larchivio è composto da schede aventi tutte la stessa dimensione e contenenti lo stesso tipo di informazione. Ogni scheda rappresenta un record. I record Per poter inserire in un file più informazioni, anche di tipo non omogeneo, raggruppate in "schede", è necessario riunirle in ununica struttura. Si deve quindi creare un nuovo tipo di dati. Tale operazione è eseguita per mezzo della struttura Type, la cui sintassi è: Type <nome> Allinterno della struttura devono essere dichiarati gli elementi che la compongono, che sono denominati campi. Per ognuno di essi deve essere specificato il tipo di dati che lo caratterizza. I campi possono essere anche di tipo totalmente diverso. Si possono infatti definire dei record contenenti contemporaneamente delle informazioni di tipo testuale, numerico e logico. Ad esempio, la seguente dichiarazione è corretta: Type Automobile Si noti che sono stati dichiarati due campi di tipo alfanumerico, uno di tipo logico e uno numerico intero. La struttura è denominata Automobile. In questo modo si è provveduto ad aggiungere un nuovo tipo di dati a quelli standard previsti da Visual Basic. È quindi possibile dichiarare la variabile MiaVettura, di tipo Automobile digitando: Dim MiaVettura As Automobile Riempimento dei campi di un record Le variabili definite come record prevedono, data la propria conformazione, una modalità di assegnamento dei valori leggermente diversa rispetto a quella prevista dalle strutture convenzionali. In genere, si esegue unoperazione di assegnamento per ogni campo, secondo la sintassi: <variabile>.<campo> = <valore> Ad esempio, volendo assegnare il valore 2499 al campo Cilindrata della variabile MiaVettura, definita in precedenza, occorre scrivere: MiaVettura.Cilindrata = 2499 Lapertura di un file ad accesso casuale Come per le strutture sequenziali, lapertura di un file ad accesso casuale avviene per mezzo dellistruzione Open che, in questo caso, assume la forma: Open
<percorso_file> dove percorso_file indica il percorso completo del file che si desidera aprire, mentre identificatore costituisce un numero utilizzato per contraddistinguere in modo univoco tale struttura e pertanto va fornito come parametro a tutti i comandi che sono destinati a gestirla. Si noti che la modalità di accesso è indicata per mezzo della parola chiave Random, che deve essere obbligatoriamente specificata, indipendentemente dal tipo di operazione che si desidera effettuare sul file, sia essa di lettura o scrittura. Si noti altresì che anche il parametro Len è obbligatorio. Esso deve contenere lesatta dimensione del record che costituisce lunità di informazione memorizzata nel file. Qualora essa non sia nota, può essere determinata per mezzo della funzione Len. Ad esempio, volendo assegnare alla variabile DimRec la dimensione del record MiaVettura, è necessario digitare: DimRec = Len(MiaVettura) Il contenuto della variabile DimRec costituisce il valore da passare come ultimo parametro allistruzione Open per consentire la gestione di un file composto da elementi di tipo Automobile. Analogamente ai file sequenziali, anche le strutture ad accesso casuale devono essere chiuse dopo luso per mezzo dellistruzione Close. La lettura di un record La lettura di un record contenuto in un file ad accesso casuale avviene per mezzo dellistruzione Get, caratterizzata dalla seguente sintassi: Get [#]<identificatore>, <posizione>, <variabile> dove <identificatore> rappresenta il numero che univocamente identifica il file oggetto delloperazione di lettura e <variabile> è il nome della variabile in cui i dati letti devono essere posti. Il parametro <posizione> indica la posizione del record da leggere. Si tratta di un valore intero compreso fra 1 e il numero dei record presenti nel file. Ad esempio, si supponga di voler accedere al quarto record presente nel file di identificatore 1 e di voler porre il suo contenuto nella variabile Dato. Ciò è possibile per mezzo della riga: Get #1, 4, Dato Solo in un caso il valore del parametro <posizione> può essere omesso; ciò si verifica in occasione delleffettuazione di operazioni di lettura in sequenza; lassenza del numero indicante la posizione provoca infatti laccesso al record successivo a quello corrente. Non possono tuttavia essere omesse le virgole di separazione. Ad esempio, la sequenza Get #1, 4, Dato provoca la lettura del quarto e del quinto record del file identificato dal numero 1. La scrittura di un record Per scrivere il contenuto di un record in un file ad accesso casuale è possibile utilizzare listruzione Put, la cui sintassi è pressoché identica a quella del comando Get: Put [#]<identificatore>, <posizione>, <variabile> In questo caso, la variabile indicata come terzo parametro contiene il dato da scrivere. Ad esempio, la riga Put #1, 5, Dato scrive il contenuto della variabile Dato nel quinto elemento del file identificato dal numero 1. Il valore assunto dal parametro <posizione> assume unimportanza fondamentale, in quanto determina se è aggiunto un nuovo record allarchivio o se ne è sovrascritto uno già esistente. Questultima evenienza si verifica quando è indicata una posizione già occupata da un elemento. Per aggiungere un nuovo record al file, invece, è necessario indicare un valore pari al numero totale dei record incrementato di ununità. La cancellazione logica di un record Il metodo più semplice per cancellare un record consiste nel sovrascriverlo con un elemento vuoto. In questo modo, tuttavia, non è possibile recuperare lo spazio da esso occupato sul disco. Si tratta cioè di una cancellazione logica, non fisica, in quanto Visual Basic non dispone di unistruzione in grado di rimuovere un record e di recuperare automaticamente lo spazio da esso occupato. È possibile sfruttare a proprio vantaggio la possibilità di effettuare solo una cancellazione logica dei record contenuti in un file per fare in modo che degli elementi eventualmente eliminati per sbaglio possano essere agevolmente recuperati. Ciò è possibile aggiungendo un campo booleano alla struttura dei record e facendo in modo che il programma che accede allarchivio consideri cancellati tutti gli elementi caratterizzati dal contenere il valore logico True allinterno di questo campo. Leliminazione di un record comporta quindi la semplice variazione del valore di un suo campo. Analogamente, è possibile recuperare un elemento cancellato per errore impostando nuovamente al valore False il campo booleano. La struttura Automobile può pertanto essere modificata come segue: Type Automobile1 La cancellazione fisica di un record Quando la quantità di informazioni da gestire diventa elevata, la necessità di recuperare lo spazio occupato dai record cancellati diventa evidente, sia per evitare lo spreco di spazio sul disco, sia per non ridurre drasticamente i tempi di accesso alle informazioni costringendo il programma a leggere dei dati inutili. Come già osservato in precedenza, Visual Basic non dispone di unistruzione in grado di provvedere automaticamente alla cancellazione fisica di un record. Tuttavia, la scrittura di una simile procedura non presenta un livello di difficoltà elevato. Essa deve solo creare un nuovo file e copiare al suo interno tutti i record non vuoti. Successivamente, deve eliminare il primo file ed assegnare il suo nome alla nuova struttura. È ciò che fa la procedura di seguito descritta, che riceve come parametro il nome del file da compattare, che si suppone composto da record di tipo Automobile1: Sub
CompattaFile(ByVal NomeFile As String) Si noti luso della funzione FreeFile, che restituisce un numero adatto ad essere utilizzato come identificatore di file ed evita così il rischio di utilizzare degli identificatori già in uso in altre parti del programma. La procedura provvede a leggere in modo sequenziale il file di cui è specificato il nome come parametro e a copiare in un file denominato Temp.dat tutti i record per i quali il campo Cancellato assume il valore False. Si noti che le operazioni di lettura e scrittura sono eseguite sequenzialmente, in quanto è stato omesso il valore indicante la posizione nelle istruzioni Get e Put. Il ciclo di copiatura termina quando sono esauriti i record da leggere. Quando ciò avviene, la funzione EOF (End Of File), già descritta nella scorsa lezione, restituisce il valore True. Dopo aver copiato tutti i record non cancellati logicamente, la procedura provvede a chiudere entrambi i file. Si noti che a tal fine utilizza ununica istruzione Close, in cui gli identificatori dei file da chiudere sono separati da una virgola. Il passo successivo consiste nel sostituire il file originale con quello creato. Ciò comporta lesecuzione di due operazioni: la cancellazione del file di origine e la ridenominazione di quello generato dalla procedura. Leliminazione avviene per mezzo dellistruzione Kill, la cui sintassi è Kill <Nome_file> Il file Temp.dat è quindi rinominato per mezzo dellistruzione Name, che è caratterizzata dalla seguente sintassi: Name <Vecchio_nome> As <Nuovo_nome> Un esempio Il Listato 2
contiene il codice di unapplicazione in grado di archiviare i dati relativi a dei
siti Internet. Per ognuno di essi, è possibile indicare lindirizzo e una breve
descrizione. È possibile creare dei nuovi record vuoti in grado di ospitare i dati
relativi a nuovi siti, oppure modificare le informazioni riferite a quelli esistenti,
nonché scorrere larchivio nei due sensi. e un esercizio Per esercitarsi sui concetti esposti, si provi a modificare lesempio sopra descritto aggiungendo la possibilità di cancellare logicamente e, su richiesta, fisicamente dei record. Conclusioni I file rivestono unimportanza
fondamentale nella maggior parte delle applicazioni, in quanto consentono di trattare una
quantità di dati superiore a quella che può essere contenuta nella memoria
dellelaboratore. Inoltre, trattandosi di strutture permanenti, permettono di
mantenere tali informazioni anche dopo lo spegnimento o il riavvio del sistema.
Lutilizzo di strutture ad accesso casuale rende ancora più evidenti i vantaggi
offerti dai file, permettendo una maggiore flessibilità duso. Maurizio Crespi si occupa principalmente di grafica e multimedia. Svolge la funzione di responsabile tecnico presso Datanord Multimedia, società specializzata nella realizzazione di software orientato al marketing e alleditoria, per la quale progetta e sviluppa applicazioni in C++, Visual Basic, Delphi e Director. Può essere contattato per e-mail come crespi@programmers.net.
|