Sei sulla pagina 1di 7

Gestione dei File in C++

Il C++ mette a disposizione un nuovo sistema di gestione


dei file più adatto alla programmazione orientata agli oggetti il
cui uso approfondito richiede conoscenze di tecniche di
programmazione che esulano dalla trattazione di questo
corso: nel seguito ne mostreremo gli aspetti essenziali,
semplificandone l'uso anche se cercheremo di resteremo il
più possibile fedeli ai meccanismi linguistici del C++.

Come noto, per memorizzare un dato in modo persistente, ad


esempio su un hard disk o un nastro, i linguaggi di
programmazione prevedono l'uso di un tipo di dato chiamato
file: dal punto di vista astratto, un file è una sequenza di byte
memorizzata su memoria di massa.

Il C++ prevede un meccanismo di gestione dei file attraverso


un'interfaccia indipendente dall'hardware: qualunque sia il
dispositivo fisico a cui il file fa riferimento, sia esso un
terminale, un unità a disco, un nastro e così via, esso viene
associato ad un dispositivo logico chiamato stream, anche
detto in italiano "flusso" o "canale", ovvero di un sistema
attraverso cui "confluiscono" le informazioni provenienti o
inviate.

Un primo esempio di canale è fornito dai dispositivi di Input-


Output (I/O):

• stdin o standard input: associato di default alla tastiera,


rappresenta il canale per l'immissione dei dati;

• stdout standard output: associato di default al video,


rappresenta il canale per l'uscita dei dati

• stderr standard output per i messaggi: associato di


default al video, rappresenta il canale con cui
rappresentare eventuali errori causati
dall'esecuzione di una istruzione.

I dispositivi standard di I/O sono “collegati” rispettivamente


agli "oggetti globali" di I/O che sono cin, cout e cerr. Per il
momento, un oggetto è da considerarsi come una variabile
istanza di una particolare implementazione di un tipo di dato
astratto, detto in C++ classe, come si vedrà nei corsi di
Programmazione Orientata agli Oggetti.

Gli oggetti globali di I/O sono definiti nel file leader


<iostream>. Tali oggetti, attraverso gli operatori di flusso <<
(inserimento) e >> (estrazione) -- rispettivamente per
cout/cerr e per cin -- permettono dunque di effettuare le
operazioni di I/O.

Si noti che un’operazione di output di un dato elemento


tramite l'operatore di inserimento << consiste nell'inserire
l'elemento nello stream di output:

stream << elemento;

ovvero, se stream è cout si ha:

cout << elemento;

Ad esempio:

#include <iostream>

int main() {

…..

cout<<"Salve Mondo\n";
}

Analogamente, un’operazione di input di un dato elemento


tramite l'operatore di estrazione consiste nell'estrarre il dato
dallo stream di input:

stream >> dato;

cin >> dato;

dove dato è una variabile di qualsiasi tipo base, oppure un


array di caratteri.

File testo e file binari.

I file gestiti in C++ sono di due tipi:

• File Testo, ovvero una sequenza di caratteri;

• File Binari, ovvero sequenza di byte associati uno a uno


con la sequenza ricevuta dal dispositivo.

Per leggere o scrivere su un file è necessario effettuare le


seguenti operazioni:

1. includere nel programma C++ la libreria <fstream> , che


contiene le definizioni necessarie per la gestione dei
file;

2. dichiarare una variabile di tipo file;

fstream mioFile;

1. Effettuare il collegamento tra la variabile dichiarata di tipo


file e lo specifico flusso da cui vengono
acquisite/scritte le informazioni: tale operazione è
anche detta "apertura del file" e in C++ viene
effettuata attivando una specifica funzione chiamata
open. Durante questa operazione è necessario
specificare la forma di accesso che si vuole
utilizzare: lettura, scrittura o entrambe.

⁃ mioFile.open("nomeFile.txt", ios::out);

1. Al termine delle operazioni sul file, questo dovrà essere


chiuso; questa operazione implica la distruzione del
nome del file stesso.

mioFile.close();

Nella tabella sono riportate alcune delle modalità di accesso


ai file più comuni:

ios::in apertura di un file in lettura

ios::out apertura di un file in scrittura

ios::binary file binario

ios::noreplace da errore se il file già esiste

ios::trunc tronca in file in apertura

ios::app apre il file in modalità append

ios::ate apre il file posizionandosi alla


fine del file

os::nocreate se il file non esiste, non cerca


di crearlo

Combinazioni tipiche ti apertura sono le seguenti:


ios::in|ios::nocreate apre il file se esiste, altrimenti da
fallimento

ios::out|ios::ate apre il file in scrittura e aggiunge i


nuovi dati alla fine, dopo quelli già
presenti

All'apertura di un file può verificarsi un errore (ad esempio se


il file non esiste o c'è qualche problema sul dispositivo): per
questo motivo, si può controllare questa eventualità attraverso
il seguente frammento di codice:

if(!mioFile) {

cout << "Impossibile aprire il file nomFile.txt.";

exit(1);

In altre parole, se l'apertura del file mioFile fallisce, mioFile


assume il valore falso e verrà invocata la funzione exit(): exit()
è una funzione di libreria standard che termina l'esecuzione
del programma quando viene invocata; l'argomento di exit() è
disponibile al programma chiamante e il valor 0 indica una
chiusura normalw del programma stesso mentre un valor
diverso da 0 una chiusura anormale. Essendo mioFile uno
stream di ingresso, è possibile utilizzare come già fatto per lo
stream cout l'operatore <<, come nel seguente frammento di
codice che memorizza un array in un file testo "nomeFile.txt".

fstream mioFile;
mioFIle.open("nomeFile.txt", ios::out);

…..

for(int i=0; i< n; i++)

mioFIle << vet[i];

mioFile.close();

Analogamente è possibile utilizzare come già fatto per lo


strema cin l'operatore <<.

Nel seguente frammento di codice ad esempio, si suppone di


aver memorizzato su un file testo una sequenza di riemp
numeri interi, con il seguente formato: il primo numero
memorizzato è la dimensione riemp dell'array; seguono
esattamente riemp elementi. Il seguente frammento di codice
permette di leggere e memorizzare la sequenza in un arra di
interi vet:

mioFile.open("input.txt", ios::in);

mioFile>>riemp;

for(int i=0; i < riemp; i++)

mioFile >> vet[i];


}

Se non si conosce il numero di elemento presenti nel file, si


può usare la funzione mioFile.eof() che restituisce vero se si è
giunti alla fine dei file, come nel seguente frammento di
codice:

i=0;

while(!mioFile.eof() )

mioFile>>vet[i++];