Gestione dei File in C++

Scrittura, lettura e modifica di file di testo e binari con la libreria <fstream>

La gestione dei file in C++ è fondamentale per salvare e recuperare dati da supporti esterni. Utilizzando la libreria <fstream>, è possibile eseguire operazioni di lettura, scrittura e modifica dei file in modo semplice ed efficiente.

🎯 Perché usare i file?
Persistenza dei dati, condivisione di informazioni, backup e configurazioni dell’applicazione

1. Classi Principali della Libreria <fstream>

📌 Le tre classi fondamentali:
Tutte ereditano da <iostream> e offrono metodi per controllare il flusso dei dati

O
ofstream

Stream di output per scrivere su file

Creazione e modifica file

ofstream fileOut("nome.txt");

I
ifstream

Stream di input per leggere da file

Lettura e elaborazione dati

ifstream fileIn("nome.txt");

F
fstream

Stream bidirezionale

Lettura e scrittura sullo stesso file

fstream fileIO("nome.txt");

2. Scrittura su File con ofstream

📌 Procedura di scrittura:
Creazione oggetto → Apertura file → Verifica → Scrittura dati → Chiusura file

2.1 Esempio di Scrittura Base

#include <iostream>
#include <fstream>
using namespace std;
int main() {
// Creazione di un oggetto ofstream per scrivere su file
ofstream fileOut(“dati.txt”);
// Verifica dell’apertura del file
if (!fileOut) {
cerr << “Errore nell’apertura del file per la scrittura.” << endl;
return 1;
}
// Scrittura di dati su file
fileOut << “Ciao, questo è un esempio di scrittura su file.” << endl;
fileOut << “Linea 2: gestione dei file in C++.” << endl;
// Chiusura del file
fileOut.close();
cout << “Dati scritti correttamente su ‘dati.txt’.” << endl;
return 0;
}

💡 Spiegazione:
Creazione oggetto: ofstream fileOut("dati.txt") crea e apre il file
Controllo errori: if (!fileOut) verifica se l’apertura è riuscita
Scrittura: Si usa l’operatore << come con cout
Chiusura: close() libera le risorse

3. Lettura da File con ifstream

📌 Procedura di lettura:
Apertura file → Verifica → Lettura riga per riga → Elaborazione → Chiusura

3.1 Esempio di Lettura Base

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream fileIn(“dati.txt”);
// Verifica dell’apertura del file
if (!fileIn) {
cerr << “Errore nell’apertura del file per la lettura.” << endl;
return 1;
}
string riga;
// Lettura del file riga per riga
while (getline(fileIn, riga)) {
cout << riga << endl;
}
// Chiusura del file
fileIn.close();
return 0;
}

💡 Spiegazione:
getline(): Legge una riga intera fino al carattere di newline
Controllo fine file: Il ciclo while si ferma automaticamente a EOF
Alternative: Si può usare anche fileIn >> per leggere parole singole

4. Operazioni Bidirezionali con fstream

🎭 Modalità di apertura:
Combina diverse flag per controllare il comportamento del file

4.1 Flag di Apertura Comuni

I
ios::in

Apertura in lettura

File deve esistere

O
ios::out

Apertura in scrittura

Crea file se non esiste

T
ios::trunc

Cancella contenuto esistente

File vuoto

A
ios::app

Scrittura in append

Mantiene contenuto esistente

4.2 Esempio di Lettura e Scrittura

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
// Apertura del file in modalità lettura e scrittura
fstream file(“dati_bidirezionale.txt”, ios::in | ios::out | ios::trunc);
if (!file) {
cerr << “Errore nell’apertura del file.” << endl;
return 1;
}
// Scrittura di dati sul file
file << “Linea 1: Dati iniziali.” << endl;
file << “Linea 2: Continuazione dei dati.” << endl;
// Per leggere il contenuto, è necessario riposizionare il cursore all’inizio
file.seekg(0);
string contenuto;
cout << “Contenuto del file:” << endl;
while (getline(file, contenuto)) {
cout << contenuto << endl;
}
file.close();
return 0;
}

💡 Spiegazione:
Combination flag: ios::in | ios::out | ios::trunc combina più modalità
seekg(0): Riposiziona il cursore di lettura all’inizio del file
Operazioni miste: Possibile alternare lettura e scrittura sullo stesso file

5. Esercizio Pratico: Rubrica di Contatti

🎯 Obiettivo:
Creare un programma che chieda all’utente di inserire contatti, salvi i dati in un file di testo e legga il file visualizzando tutti i contatti

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Contatto {
string nome;
string telefono;
};
int main() {
int n;
cout << “Quanti contatti vuoi inserire? “;
cin >> n;
cin.ignore(); // Pulisce il buffer
// Creazione del file in modalità scrittura
ofstream rubricaOut(“rubrica.txt”);
if (!rubricaOut) {
cerr << “Errore nell’apertura del file per la scrittura.” << endl;
return 1;
}
Contatto contatto;
for (int i = 0; i < n; i++) {
cout << “\nInserisci il nome del contatto “ << i + 1 << “: “;
getline(cin, contatto.nome);
cout << “Inserisci il numero di telefono: “;
getline(cin, contatto.telefono);
// Scrive il contatto nel file, separando i campi con una virgola
rubricaOut << contatto.nome << “,” << contatto.telefono << endl;
}
rubricaOut.close();
// Lettura e visualizzazione dei contatti dal file
ifstream rubricaIn(“rubrica.txt”);
if (!rubricaIn) {
cerr << “Errore nell’apertura del file per la lettura.” << endl;
return 1;
}
cout << “\n— Rubrica dei Contatti —“ << endl;
string linea;
while (getline(rubricaIn, linea)) {
cout << linea << endl;
}
rubricaIn.close();
return 0;
}

💡 Caratteristiche dell’esercizio:
Struct Contatto: Organizza i dati in modo strutturato
cin.ignore(): Pulisce il buffer dopo cin >>
Formato CSV: Campi separati da virgola per una facile elaborazione
Doppia operazione: Scrittura e successiva lettura dello stesso file

6. Esercizio Avanzato: Registro delle Presenze

🎯 Obiettivo:
Implementa un programma che registri le presenze degli studenti, salvi i dati in un file, calcoli e visualizzi il totale delle presenze

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Presenza {
string nomeStudente;
bool presente; // true = presente, false = assente
};
int main() {
int n;
cout << “Quanti studenti vuoi registrare? “;
cin >> n;
cin.ignore();
ofstream registroOut(“registro_presenze.txt”);
if (!registroOut) {
cerr << “Errore nell’apertura del file per la scrittura.” << endl;
return 1;
}
Presenza studente;
for (int i = 0; i < n; i++) {
cout << “\nInserisci il nome dello studente “ << i + 1 << “: “;
getline(cin, studente.nomeStudente);
char risposta;
cout << “Lo studente è presente? (s/n): “;
cin >> risposta;
cin.ignore();
studente.presente = (risposta == ‘s’ || risposta == ‘S’);
// Salva il record nel file
registroOut << studente.nomeStudente << “,” << (studente.presente ? “Presente” : “Assente”) << endl;
}
registroOut.close();
// Lettura del registro e calcolo del totale delle presenze
ifstream registroIn(“registro_presenze.txt”);
if (!registroIn) {
cerr << “Errore nell’apertura del file per la lettura.” << endl;
return 1;
}
int totalePresenze = 0;
string record;
cout << “\n— Registro Presenze —“ << endl;
while (getline(registroIn, record)) {
cout << record << endl;
// Se il record contiene “Presente”, incrementa il contatore
if (record.find(“Presente”) != string::npos) {
totalePresenze++;
}
}
registroIn.close();
cout << “\nTotale presenze: “ << totalePresenze << endl;
return 0;
}

💡 Caratteristiche dell’esercizio:
Input interattivo: L’utente inserisce dati dinamicamente
Conversione bool: Trasforma risposta s/n in valore booleano
Operatore ternario: condizione ? vero : falso per scegliere il testo
string::find(): Cerca sottostringhe per contare le presenze

7. Best Practices e Consigli

Regole fondamentali:

✅ Controllo Errori

Verifica sempre se il file è stato aperto correttamente con if (!file)

✅ Chiusura File

Chiudi sempre il file con close() per liberare risorse

✅ Gestione Buffer

Usa cin.ignore() dopo cin >> per pulire il buffer

✅ Modalità Appropriate

Scegli le flag giuste (ios::app, ios::trunc) per ogni operazione

✅ Formato Dati

Usa separatori consistenti (virgole, punti e virgola) per file strutturati

Conclusioni

Punti chiave della gestione file:

✅ ofstream

Per scrivere dati su file, creazione e modifica contenuti

✅ ifstream

Per leggere dati da file, elaborazione e analisi

✅ fstream

Per operazioni bidirezionali, lettura e scrittura combinate

✅ Applicazioni Pratiche

Rubriche, registri, configurazioni, salvataggio dati applicazione

La gestione dei file con <fstream> in C++ consente di interagire con dati esterni in modo semplice ed efficiente. Attraverso gli esempi sopra riportati è possibile gestire dati strutturati, applicare best practices per evitare errori e creare applicazioni che persistono i dati tra diverse esecuzioni. Buon coding! 🚀

Torna in alto