Come configurare smartphone e PC. Portale informativo
  • casa
  • notizia
  • Lavorare con due file c. Scrittura - lettura di informazioni

Lavorare con due file c. Scrittura - lettura di informazioni

Per facilità di gestione, le informazioni nei dispositivi di archiviazione vengono archiviate sotto forma di file.

File - area denominata memoria esterna, allocato per memorizzare l'array di dati. I dati contenuti nei file sono della natura più disparata: algoritmici o linguaggio macchina; dati iniziali per il funzionamento dei programmi o risultati dell'esecuzione del programma; testi liberi; immagini grafiche eccetera.

Directory (cartella, directory) - una raccolta denominata di byte su un supporto di memorizzazione contenente i nomi di sottodirectory e file, utilizzata nel file system per semplificare l'organizzazione dei file.

file system chiamata parte funzionale sistema operativo A che esegue operazioni sui file. Esempi di file system sono FAT (FAT - File Allocation Table, file allocation table), NTFS, UDF (usato sui CD).

Esistono tre versioni principali di FAT: FAT12, FAT16 e FAT32. Differiscono per il numero di record nella struttura del disco, ad es. il numero di bit allocati per memorizzare il numero del cluster. FAT12 viene utilizzato principalmente per floppy disk (fino a 4 KB), FAT16 per dischi piccoli, FAT32 per unità FLASH grande capacità(fino a 32 GB).

Considera la struttura file system usando FAT32 come esempio.

Struttura del file FAT32

I dispositivi di memoria esterna nel sistema FAT32 non sono byte, ma indirizzamento a blocchi. Le informazioni vengono scritte su un dispositivo di memoria esterno in blocchi o settori.

Settore: l'unità minima indirizzabile di archiviazione delle informazioni su dispositivi di archiviazione esterni. In genere, la dimensione del settore è fissata a 512 byte. Per aumentare lo spazio degli indirizzi dei dispositivi di memoria esterni, i settori vengono combinati in gruppi chiamati cluster.

Un cluster è un'associazione di più settori, che può essere considerata come un'unità indipendente con determinate proprietà. La proprietà principale di un cluster è la sua dimensione, misurata nel numero di settori o nel numero di byte.

Il file system FAT32 ha la struttura seguente.

I cluster utilizzati per la scrittura dei file sono numerati a partire da 2. Di norma, il cluster n. 2 viene utilizzato dalla directory principale e, a partire dal cluster n. 3, viene archiviato l'array di dati. I settori utilizzati per memorizzare le informazioni al di sopra della directory principale non sono raggruppati.
La dimensione minima del file su disco è 1 cluster.

Il settore di avvio inizia con le seguenti informazioni:

  • EB 58 90 - ramo e firma incondizionati;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 - il numero di byte nel settore (solitamente 512);
  • 1 byte - il numero di settori nel cluster;
  • 2 byte - il numero di settori di riserva.

Inoltre, il settore di avvio contiene le seguenti informazioni importanti:

  • 0x10 (1 byte) – numero di tabelle FAT (solitamente 2);
  • 0x20 (4 byte) - il numero di settori sul disco;
  • 0x2C (4 byte) – numero del cluster della directory principale;
  • 0x47 (11 byte) – etichetta del volume;
  • 0x1FE (2 byte) - firma settore di avvio(55AA).

Il settore delle informazioni sul file system contiene:

  • 0x00 (4 byte) – firma (52 52 61 41 );
  • 0x1E4 (4 byte) – firma (72 72 41 61 );
  • 0x1E8 (4 byte) – numero di cluster liberi, -1 se non noto;
  • 0x1EC (4 byte) – numero dell'ultimo cluster registrato;
  • 0x1FE (2 byte) - firma (55 AA).

La tabella FAT contiene informazioni sullo stato di ciascun cluster sul disco. I 2 byte inferiori della tabella FAT memorizzano F8 FF FF 0F FF FF FF FF (corrispondente allo stato dei cluster 0 e 1, fisicamente assente). Inoltre, lo stato di ogni cluster contiene il numero del cluster in cui continua il file corrente o le seguenti informazioni:

  • 00 00 00 00 – il cluster è libero;
  • FF FF FF 0F è la fine del file corrente.
  • 8 byte - nome file;
  • 3 byte - estensione del file;

La directory principale contiene una serie di record di informazioni a 32 bit per ciascun file contenente le seguenti informazioni:

In caso di lavoro con nomi lunghi file (compresi i nomi russi), il nome del file è codificato nel sistema di codifica UTF-16. In questo caso vengono allocati 2 byte per la codifica di ogni carattere. In questo caso, il nome del file viene scritto nella forma della seguente struttura:

  • sequenza da 1 byte;
  • 10 byte contengono i 5 caratteri inferiori del nome del file;
  • attributo da 1 byte;
  • 1 byte riservato;
  • 1 byte - somma di controllo nome DOS;
  • 12 byte contengono i 3 caratteri inferiori del nome del file;
  • 2 byte – numero del primo cluster;
  • i restanti caratteri del nome lungo.

Lavorare con i file in C

Per il programmatore apri il file rappresentato come una sequenza di dati letti o scritti. Quando un file viene aperto, viene associato a Flusso di I/O. Le informazioni di output vengono scritte nel flusso, le informazioni di input vengono lette dal flusso.

Quando un flusso viene aperto per l'I/O, viene associato alla struttura standard di tipo FILE , definita in stdio.h . La struttura FILE contiene informazione necessaria sul file.

L'apertura di un file viene eseguita utilizzando la funzione fopen(), che restituisce un puntatore a una struttura di tipo FILE , che può essere utilizzata per operazioni successive sul file.

FILE *fopen(nome, tipo);


name è il nome del file da aprire (compreso il percorso),
type è un puntatore a una stringa di caratteri che definisce come si accede al file:
  • "r" - aprire il file per la lettura (il file deve esistere);
  • "w" - aperto file vuoto per la registrazione; se il file esiste, il suo contenuto viene perso;
  • "a" - aprire il file per scrivere fino alla fine (per aggiungere); il file viene creato se non esiste;
  • "r+" - aprire il file per la lettura e la scrittura (il file deve esistere);
  • "w+" - apre un file vuoto per leggere e scrivere; se il file esiste, il suo contenuto viene perso;
  • "a+" - apre il file per la lettura e l'aggiunta, se il file non esiste, viene creato.

Il valore restituito è un puntatore al flusso aperto. Se viene rilevato un errore, viene restituito NULL.

La funzione fclose() chiude lo stream o gli stream associati ai file aperti con fopen(). Il flusso da chiudere è determinato dall'argomento della funzione fclose().

Valore restituito: valore 0 se il flusso è stato chiuso correttamente; la costante EOF se si è verificato un errore.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#includere
int main() (
FILE *fp;
nome carattere = "mio.txt" ;
if ((fp = fopen(name, "r" )) == NULL )
{
printf( "Impossibile aprire il file");
getchar();
restituire 0;
}
// apertura del file riuscita
... // azioni richieste sui dati
fclose(fp);
getchar();
restituire 0;
}

Lettura di un carattere da un file:

char fgetc(flusso);


L'argomento della funzione è un puntatore a un flusso di tipo FILE . La funzione restituisce il codice del carattere letto. Se viene raggiunta la fine del file o si verifica un errore, viene restituita la costante EOF.

Scrivere un carattere in un file:

fputc(carattere, flusso);

Gli argomenti della funzione sono un carattere e un puntatore a un flusso di tipo FILE . La funzione restituisce il codice del carattere letto.

Le funzioni fscanf() e fprintf() sono simili funzioni di scansione() e printf() , ma operano su file di dati e hanno un puntatore a file come primo argomento.

fscanf(stream, "InputFormat" , args);

Scrivi informazioni a file di testo abbiamo già imparato. – Se non hai imparato, consulta l'articolo precedente. È descritto e dettagliato

Ma cosa succede se il file esiste già e abbiamo bisogno di leggere le informazioni da esso per l'elaborazione? Fortunatamente, anche questo è abbastanza semplice. Ti ricordo che ci sono diverse opzioni per implementare questo compito, ne ho descritto solo uno. Viene descritto quello che per qualche ragione mi sembra il più semplice per la percezione.

#includere

int principale()
{
carattere s1 //La variabile leggerà la stringa
ifstream in("C:\\\FromC\\myfile.txt"); //Apertura del file per la lettura delle informazioni
in >>s1 ; //linea di lettura
in.close() // Chiusura del file

cout<Valore di uscita s1 sullo schermo
ritorno 0 ;
}

Ecco il programma più semplice per leggere la prima riga da un file di testo che si trova lungo il percorso
C:\\\DaC\\miofile.txt -
Poiché questa è una continuazione dell'ultimo articolo, ho deciso di utilizzare il file che abbiamo creato lì. Difficoltà con questo, probabilmente non dovrebbero sorgere.
Ma torniamo al codice. Innanzitutto, apriamo il file per leggere le informazioni da esso, per questo utilizziamo il comando se flusso, tra parentesi indichiamo o il nome del file o il percorso del file, come ho fatto io. ("C:\\\FromC\\miofile.txt");
Quando abbiamo aperto il file per leggerne qualcosa, abbiamo dichiarato una variabile di tipo char-
carattere s1
Ora dobbiamo solo assegnare il valore di una riga dal file alla variabile. Questo è ciò che facciamo come squadra. in
Prestare attenzione alle parentesi angolari in >>
In realtà, come si evince dai commenti al codice del programma, affinché la variabile assegni un valore leggibile, dobbiamo scriverlo dopo in >>
in >>s1 ;

Niente di speciale compito difficile questo non sembra essere il caso, soprattutto se hai già perfettamente padroneggiato e imparato come utilizzare il materiale dell'ultimo articolo - tutto è assolutamente simile, solo 2 comandi sono diversi

Creazione di un file e scrittura di informazioni su di esso C++

fuoriuscita fuori ( Nome del file );
fuori<< (Stringa scritta);
fuori.chiudere();
=============================

Leggere il testo da un file e visualizzare il testo sullo schermo in C++

ifstream in (Nome del file );
in>> (Leggere una riga);
in.chiudere();(Chiudi il file)
============================
Scriviamo un semplice programma, che leggerà l'input di testo dalla tastiera e lo scriverà in un file:

#includere
#includere

int principale()
{
\\ 3 linee future
clrscsr(); // Cancellare lo schermo

cout<<“Wwedi pervuu stroku” ; cin >>a ; fine;
cout<<“Wwedi wtoruu stroku” ; cin >>b ; fine;
cout<<“Wwedi tretuu stroku” ; cin >>c ; fine;
clrscr(); //

/*Inizia a lavorare con il file*/
ofstream out("C:\\\FromC\\myfile.txt"); //Apertura di un file per la scrittura
fuori<Annota la prima riga
fuori<Annota la seconda riga
fuori<Annota la terza riga
out.close(); // Chiusura del file

//Ripristina variabili

per (int io =0 ;i<=255 ;i ++)
(a =*“” ; b =*“” ; c =*“” ;)


ifstream in(“C:\\\FromC\\myfile.txt”);
in >>a >>b >>c ; //Leggiamo ogni nuova riga in una nuova variabile
in.close(); // Chiusura del file

/* */

per (i =0 ;a !=*"" ;i ++)
{
se (i > sizeof(a)) rottura ;
cout<

}
cout<<“\n” ; \\

/* */


{
se (i >dimensione(b)) rottura ;
cout<
}
cout<<“\n” ; \\ Sposta il cursore su una nuova riga

/* */

per (i =0 ;c !=*“” ;i ++)
{
se (i >dimensione(c)) rottura ;
cout<<с ;
}

ritorno 0 ;
}
===================

Negli esempi sopra, ce n'è uno di questi ENORME difetto. Se proviamo a inserire una riga contenente spazi, il programma non funzionerà come necessario. Probabilmente, non solo io, ma anche molte altre persone si sono imbattute in questo errore. Pertanto, lascio il codice fornito in modo errato in modo che tu possa vedere cosa potresti incontrare.

Dal momento che non ci sono libri a casa, ho ricominciato a setacciare Internet e ho trovato un sacco di assurdità complicate. Tuttavia, in qualche modo ho trovato una soluzione al mio problema.
Mi ha aiutato a leggere di cosa cout sostiene i suoi metodi. E su internet tutti i consigli vanno all'utilizzo della funzione getline Con mia grande felicità, ho scoperto come utilizzare questa funzione molto rapidamente e poi l'ho usata nel codice.
In generale, vale la pena menzionare e descrivere questa funzione, ma finora non la capisco davvero, capisco solo che deve essere usata e capire come, quindi fornisco un esempio più corretto del nostro programma in fase di sviluppo:

#includere
#includere

int principale()
{
caratteri a ,b ,c ; \\ 3 linee future
clrscsr(); // Cancellare lo schermo

/* Inserisci i valori per le variabili */

cout<<“Wwedi pervuu stroku” ; cin.getline(a,sizeof(a)); fine;
cout<<“Wwedi wtoruu stroku” ; cin.getline(a,sizeof(b)); fine;
cout<<“Wwedi tretuu stroku” ; cin.getline(a,sizeof(c)); fine;
clrscr(); //Dopo aver inserito i valori, lo schermo è stato cancellato

/*Inizia a lavorare con il file*/
ofstream out("C:\\\FromC\\myfile.txt"); // Apertura di un file per la scrittura
fuori<
Annota la prima riga
fuori<Annota la seconda riga
fuori<Annota la terza riga
out.close(); // Chiusura del file

//Ripristina variabili

per (int io =0 ;i<=255 ;i ++)
(a =*“” ; b =*“” ; c=*“” ;)

/*Continua a lavorare con il file*/

se trasmetti in (“C:\\\FromC\\myfile.txt”);
in.getline(a,sizeof(a));// ma
in.getline(b,sizeof(b));// Lettura di una stringa in una variabile B
in.getline(c,sizeof(c)); // Lettura di una stringa in una variabile C
in.close(); // Chiusura del file

/* Leggiamo la prima riga carattere per carattere e la visualizziamo sullo schermo */

per (i =0 ;a !=*"" ;i++)
{
se (i > sizeof(a)) rottura ;
cout<

}
cout<<“\n” ; \\ Sposta il cursore su una nuova riga

/* Leggiamo la seconda riga carattere per carattere e la visualizziamo sullo schermo */

per (i =0 ;b !=*“” ;i ++)
{
se (i >dimensione(b)) rottura ;
cout<
}
cout<<“\n” ; \\ Sposta il cursore su una nuova riga

/* Leggiamo la terza riga carattere per carattere e la visualizziamo sullo schermo */

for (i =0 ;c !=*“” ;i++)
{
se (i>dimensione(c)) rottura ;
cout<<с[i];
}

getch(); \\In attesa che venga premuto il tasto Invio
ritorno 0 ;
}
===================

In questo materiale viene analizzato un esempio di lettura di informazioni carattere per carattere. Dal momento che non ho descritto il lavoro con le variabili di tipo car, i principianti potrebbero riscontrare qualche inconveniente nella comprensione del codice. Solo che non sapevo di che tipo car ha alcune caratteristiche e ho pensato che tutto fosse più semplice. Pertanto, alcuni momenti incomprensibili del programma di cui sopra possono essere letti nel seguente articolo. lavorare con char in C++ per principianti

In caso contrario, l'esempio fornito, come leggere le righe da un file di testo in C++, dovrebbe essere accessibile e abbastanza comprensibile. Questa non è la migliore opzione di implementazione in questo momento e ho perso alcuni punti importanti, ma dal momento che stiamo iniziando a imparare il linguaggio C ++, per ora è abbastanza. Più tardi, probabilmente arriverò al perduto, ma ora devi percepire solo il più necessario.

Se comprendiamo questo materiale insieme a voi, allora abbiamo fatto un piccolo passo verso la nostra professionalità.

Nota:
rottura ;– Questo è il comando che esce dal ciclo. Abbiamo se il contacicli per diventa maggiore della dimensione dichiarata della variabile carbone, quindi usciamo forzatamente dal ciclo
!= – questa è la nostra condizione. Denota una tale disuguaglianza di condizione
se(a!=b)- leggi come se un non uguale B

fine; - Questa è una traduzione del cursore in una nuova riga all'interno della console (per quanto ho capito)
Questo comando è simile a "\n"

La maggior parte dei programmi per computer funziona con i file e quindi è necessario creare, eliminare, scrivere, leggere, aprire file. Che cos'è un file? Un file è una raccolta denominata di byte che può essere archiviata su un dispositivo di archiviazione. Bene, ora è chiaro che un file è una sequenza di byte che ha un nome univoco, come un file .txt. I file con lo stesso nome non possono trovarsi nella stessa directory. Il nome del file è inteso non solo come nome, ma anche come estensione, ad esempio: file.txt e file.dat file diversi, anche se hanno lo stesso nome. Esiste qualcosa come il nome completo dei file: questo è l'indirizzo completo della directory del file con il nome del file, ad esempio: D:\docs\file.txt . È importante comprendere questi concetti di base, altrimenti sarà difficile lavorare con i file.

Per lavorare con i file, devi includere un file di intestazione . IN diverse classi definite e file di intestazione inclusi input di file e output di file.

L'I/O su file è simile all'I/O standard, l'unica differenza è che l'I/O non viene eseguito sullo schermo, ma su un file. Se l'input/output su dispositivi standard viene eseguito utilizzando gli oggetti cin e cout, per organizzare l'I/O dei file è sufficiente creare i propri oggetti che possono essere utilizzati in modo simile agli operatori cin e cout.

Ad esempio, è necessario creare un file di testo e scrivervi la riga Lavorare con i file in C++. Per fare ciò, è necessario eseguire i seguenti passaggi:

  1. creare un oggetto di classe ofstream ;
  2. associare un oggetto classe al file su cui scrivere;
  3. scrivere una riga in un file;
  4. chiudi il file.

Perché è necessario creare un oggetto della classe ofstream e non della classe ifstream? Perché è necessario scrivere su un file e se è necessario leggere i dati da un file, verrà creato un oggetto della classe ifstream.

// crea un oggetto da scrivere nel file ofstream /*nome oggetto*/; // oggetto della classe ofstream

Chiamiamo l'oggetto - fout , ecco cosa succede:

Fuori dal flusso;

Perché abbiamo bisogno di un oggetto? L'oggetto è necessario per poter scrivere nel file. L'oggetto è già stato creato, ma non è associato al file in cui deve essere scritta la stringa.

fout.open("cppstudio.txt"); // associa l'oggetto al file

Attraverso l'operazione punto, otteniamo l'accesso al metodo della classe open(), tra parentesi indichiamo il nome del file. Il file specificato verrà creato nella directory corrente con il programma. Se esiste un file con lo stesso nome, il file esistente verrà sostituito da quello nuovo. Quindi, il file è aperto, resta da scrivere la riga desiderata. Si fa così:

Fout<< "Работа с файлами в С++"; // запись строки в файл

Usando l'operazione cast to stream insieme all'oggetto fout, la stringa Gestione file in C++ viene scritta in un file. Poiché non è più necessario modificare il contenuto del file, è necessario chiuderlo, ovvero separare l'oggetto dal file.

fout.close(); // chiudi il file

Di conseguenza, è stato creato un file con la riga Lavorare con i file in C++.

I passaggi 1 e 2 possono essere combinati, ovvero in una riga creare un oggetto e associarlo a un file. Si fa così:

Offstream fout("cppstudio.txt"); // crea un oggetto della classe ofstream e lo associa al file cppstudio.txt

Uniamo tutto il codice e otteniamo il seguente programma.

// file.cpp: definisce il punto di ingresso per l'applicazione console. #include "stdafx.h" #include usando lo spazio dei nomi std; int main(int argc, char* argv) ( ofstream fout("cppstudio.txt"); // crea un oggetto della classe ofstream per la scrittura e lo associa al file cppstudio.txt fout<< "Работа с файлами в С++"; // запись строки в файл fout.close(); // закрываем файл system("pause"); return 0; }

Resta da verificare il corretto funzionamento del programma e per questo apriamo il file cppstudio.txt e guarda il suo contenuto, dovrebbe essere - Lavorare con i file in C++.

  1. creare un oggetto della classe ifstream e associarlo al file da cui leggere;
  2. leggere file;
  3. chiudi il file.
// file_read.cpp: definisce il punto di ingresso per l'applicazione console. #include "stdafx.h" #include #includere usando lo spazio dei nomi std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // corretta visualizzazione dell'alfabeto cirillico char buff; // buffer di memorizzazione intermedio del testo letto dal file ifstream fin("cppstudio.txt "); // ha aperto il file per leggere fin >><< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку system("pause"); return 0; }

Il programma mostra due modi per leggere da un file, il primo utilizza l'operazione di trasferimento in streaming, il secondo utilizza la funzione getline() . Nel primo caso viene letta solo la prima parola e nel secondo caso viene letta una stringa di 50 caratteri. Ma poiché nel file sono rimasti meno di 50 caratteri, i caratteri vengono letti fino all'ultimo compreso. Si noti che leggendo una seconda volta (riga 17) continuava dopo la prima parola, e non dall'inizio, poiché la prima parola era stata lettariga 14. Il risultato del programma è mostrato in Figura 1.

Lavorare con i file in C++ Premere un tasto qualsiasi per continuare. . .

Figura 1 - Utilizzo di file in C++

Il programma ha funzionato correttamente, ma non è sempre così, anche se tutto è in ordine con il codice. Ad esempio, il nome di un file inesistente è stato passato al programma o è stato commesso un errore nel nome. Cosa poi? In questo caso, non succederà nulla. Il file non verrà trovato, il che significa che non è possibile leggerlo. Il compilatore pertanto ignorerà le righe in cui si manipola il file. Di conseguenza, il programma uscirà correttamente, ma sullo schermo non verrà visualizzato nulla. Sembrerebbe che questa sia una reazione del tutto normale a una situazione del genere. Ma un semplice utente non capirà quale sia il problema e perché una riga del file non è apparsa sullo schermo. Quindi, per rendere tutto molto chiaro, C++ fornisce una tale funzione - is_open() , che restituisce valori interi: 1 - se il file è stato aperto correttamente, 0 - se il file non è stato aperto. Concludiamo il programma con l'apertura del file, in modo tale che se il file non viene aperto, viene visualizzato un messaggio corrispondente.

// file_read.cpp: definisce il punto di ingresso per l'applicazione console. #include "stdafx.h" #include #includere usando lo spazio dei nomi std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // visualizzazione corretta del cirillico char buff; // buffer di archiviazione intermedio del testo letto dal file ifstream fin("cppstudio.doc"); / / ( INSERITO NOME FILE ERRATO) if (!fin.is_open()) // se il file non è aperto cout<< "Файл не может быть открыт!\n"; // сообщить об этом else { fin >> buff; // legge la prima parola dal file cout<< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку } system("pause"); return 0; }

Il risultato del programma è mostrato in Figura 2.

Impossibile aprire il file! Premere un tasto qualsiasi per continuare. . .

Figura 2 - Utilizzo di file in C++

Come puoi vedere dalla Figura 2, il programma ha segnalato che non è stato possibile aprire il file. Pertanto, se il programma sta lavorando con i file, si consiglia di utilizzare questa funzione, is_open() , anche se si è sicuri che il file esista.

Modalità di apertura dei file

Le modalità di apertura dei file determinano come vengono utilizzati i file. Per impostare la modalità, la classe ios_base fornisce costanti che determinano la modalità di apertura del file (vedere la tabella 1).

Le modalità di apertura dei file possono essere impostate direttamente durante la creazione di un oggetto o quando si chiama la funzione open() .

Ofstream fout("cppstudio.txt", ios_base::app); // apre il file per aggiungere informazioni alla fine del file fout.open("cppstudio.txt", ios_base::app); // apre il file per aggiungere informazioni alla fine del file

Le modalità di apertura dei file possono essere combinate utilizzando un'operazione booleana bit per bit o| , ad esempio: ios_base::out | ios_base::trunc - apre un file per la scrittura, dopo averlo cancellato.

Gli oggetti della classe ofstream , se associati a file, per impostazione predefinita contengono modalità di apertura file ios_base::out | ios_base::trunc . Cioè, il file verrà creato se non esiste. Se il file esiste, il suo contenuto verrà eliminato e il file stesso sarà pronto per la registrazione. Gli oggetti della classe ifstream, quando associati a un file, hanno per impostazione predefinita la modalità di apertura del file ios_base::in - il file è aperto in sola lettura. La modalità di apertura del file è anche chiamata flag, per leggibilità useremo questo termine in futuro. La tabella 1 non elenca tutti i flag, ma questi dovrebbero essere sufficienti per iniziare.

Tieni presente che i flag ate e app sono molto simili nella descrizione, entrambi spostano il puntatore alla fine del file, ma il flag app consente di scrivere solo alla fine del file e il flag ate semplicemente riorganizza il flag al fine del file e non limita lo spazio di registrazione.

Sviluppiamo un programma che, utilizzando l'operazione sizeof(), calcolerà le caratteristiche dei principali tipi di dati in C++ e le scriverà su un file. Caratteristiche:

  1. il numero di byte allocati per il tipo di dati
  2. il valore massimo che un particolare tipo di dati può memorizzare.

La scrittura su un file deve essere nel seguente formato:

/ * Tipo di dati Byte Valore massimo BOOL = 1 255.00 Char = 1 255.00 breve int = 2 32767.00 Unsigned short int = 2 65535.00 int = 4 65535.00 int = 4 2147483647.00 Unsigned int = 4 4294967295.00 lungo int = 4 214748364.00 Unsigned long int = 4 4294967295.00 float = 4 214748364.00 galleggiante lungo = 8 9223372036854775800.00 doppio = 8 9223372036854775800.00 */

Tale programma è già stato sviluppato in precedenza nella sezione, ma tutte le informazioni sui tipi di dati sono state inviate al dispositivo di output standard e dobbiamo rifare il programma in modo che le informazioni vengano scritte su un file. Per fare ciò, è necessario aprire il file in modalità scrittura, con troncamento preliminare delle informazioni sul file corrente ( riga 14). Una volta che il file è stato creato e aperto con successo (righe 16 - 20), al posto dell'istruzione cout, in riga 22 usa l'oggetto fout. quindi, invece di una schermata, le informazioni sui tipi di dati verranno scritte su un file.

// write_file.cpp: definisce il punto di ingresso per l'applicazione console. #include "stdafx.h" #include #includere // lavora con i file #include // Manipolatori di I/O che usano lo spazio dei nomi std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // collega l'oggetto al file, aprendo il file in modalità di scrittura, cancellando prima tutti i dati ofstream fout("data_types.txt ", ios_base::out | ios_base::trunc); if (!fout.is_open()) // se il file non è stato aperto ( cout<< "Файл не может быть открыт или создан\n"; // напечатать соответствующее сообщение return 1; // выполнить выход из программы } fout << " data type " << "byte" << " " << " max value "<< endl // intestazioni di colonna <<"bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "long float = " << sizeof(long float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout << "Данные успешно записаны в файл data_types.txt\n"; system("pause"); return 0; }

È impossibile non notare che le modifiche al programma sono minime, e tutto grazie al fatto che l'input/output standard e l'input/output file vengono utilizzati esattamente allo stesso modo. Al termine del programma,riga 45abbiamo chiuso in modo esplicito il file, sebbene ciò non sia richiesto, è considerata una buona pratica di programmazione. Vale la pena notare che tutte le funzioni e i manipolatori utilizzati per la formattazione dell'input/output standard sono rilevanti anche per l'input/output dei file. Pertanto, non si sono verificati errori quando l'operatore cout è stato sostituito da un oggetto fout.

Lavorare con file di testo in C++.

Esistono due tipi principali di file: di testo e binari. I file consentono all'utente di leggere grandi quantità di dati direttamente dal disco senza digitarli dalla tastiera.

    Testo sono chiamati file composti da qualsiasi carattere. Sono organizzati in righe, ognuna delle quali termina con un carattere di fine riga. La fine del file stesso è indicata dal simbolo "fine file". Quando si scrivono informazioni in un file di testo, che può essere visualizzato utilizzando qualsiasi editor di testo, tutti i dati vengono convertiti in un tipo di carattere e archiviati sotto forma di carattere.

    IN binario Nei file, le informazioni vengono lette e scritte sotto forma di blocchi di una certa dimensione, in cui possono essere archiviati dati di qualsiasi tipo e struttura.

Per lavorare con i file, speciale tipi di dati, chiamata i flussi. Flusso ifstream viene utilizzato per lavorare con i file in modalità di lettura e fuoriuscita in modalità di registrazione. Uno stream viene utilizzato per lavorare con i file sia in scrittura che in lettura. fstream.

Nei programmi C++, quando si lavora con file di testo, è necessario includere le librerie iostream e fstream.

In modo da annotare dati in un file di testo, è necessario:

    descrivere una variabile di tipo di flusso.

    informazioni di output su un file.

    assicurati di chiudere il file.

Per letture dati da un file di testo, è necessario:

    descrivere una variabile di tipo ifstream.

    aprire un file utilizzando la funzione di apertura.

    chiudi il file.

Registrazione informazioni in un file di testo

    Come accennato in precedenza, per iniziare a lavorare con un file di testo, è necessario dichiarare una variabile del tipo ofstream. Ad esempio, in questo modo:

    Verrà creata una variabile F per scrivere informazioni nel file.

    Il passaggio successivo consiste nell'aprire il file per la scrittura. In generale, l'operatore di apertura del flusso sarà simile a:

F. open("file", modalità);

Qui F è una variabile dichiarata come ofstream,

file - il nome completo del file sul disco,

modalità - modalità di funzionamento con il file aperto.

Si noti che quando si specifica il nome completo del file, è necessario inserire una doppia barra. Ad esempio, il nome completo del file noobs.txt che si trova nella cartella del gioco sull'unità D: dovrà essere scritto in questo modo:

D:\\gioco\\noobs.txt.

Il file può essere aperto in una delle seguenti modalità:

ios::in - apri il file in modalità di lettura dei dati, questa modalità è la modalità predefinita per i flussi ifstream;

ios::out - apre il file in modalità di scrittura dati (in questo caso, le informazioni sul file esistente vengono distrutte), questa modalità è la modalità predefinita per i flussi di flusso;

ios::app - apre un file nella modalità di scrittura dei dati alla fine del file;

ios::ate - si sposta alla fine di un file già aperto;

ios::trunc - cancella il file, lo stesso accade in modalità ios::out;

ios::nocreate - non aprire il file se non esiste;

ios::noreplace - Non aprire un file esistente.

Il parametro mode potrebbe essere assente, nel qual caso il file viene aperto nella modalità predefinita per questo flusso.

Dopo una corretta apertura del file (in qualsiasi modalità), la variabile F memorizzerà true, altrimenti false. Questo verificherà la correttezza dell'operazione di apertura del file.

Puoi aprire un file (prendiamo ad esempio D:\\game\\noobs.txt) in modalità di scrittura usando uno dei seguenti metodi:

// primo strada

offstream F;

F.open("D:\\gioco\\noobs.txt", ios::out);

//secondo modo, ios::out mode è la modalità predefinita

// per flussofuoriuscita

offstream F;

//il terzo modo combina la descrizione della variabile e il tipo di flusso

//e apri il file in un'unica istruzione

ofstream F("D:\\gioco\\noobs.txt", ios::out);

Dopo aver aperto un file in modalità di scrittura, verrà creato un file vuoto in cui è possibile scrivere le informazioni.

Se vuoi aprire un file esistente in modalità di pre-scrittura, usa ios::app come modalità.

Dopo aver aperto un file in modalità scrittura, puoi scriverci come sullo schermo, solo al posto del dispositivo di output standardcoutè necessario specificare il nome del file aperto.

Ad esempio, per scrivere la variabile a nello stream F, l'istruzione di output sarebbe:

Per stampare in sequenza le variabili b, c, d sul flusso G, l'istruzione di output diventa:

G<

Il flusso viene chiuso utilizzando l'operatore:

ESEMPIO:

Crea un file di testo D:\\game\\noobs.txt e scrivici n numeri reali.

#include "stdafx.h"

#includere

#includere

#includere

usando lo spazio dei nomi std;

int principale()

setlocale(LC_ALL, "RUS");

int io, n;

doppia a;

//descrive un flusso per la scrittura di dati in un file

fuoriuscita F;

//apri il file in modalità di scrittura,

//modalitàios:: fuoriinstallato per impostazione predefinita

f.open("D:\\gioco\\noobs.txt", ios::out);

//inserisci il numero di numeri reali

cout<<" n="; cin>> n;

//ciclo per l'inserimento di numeri reali

//e scrivendoli in un file

per (i=0; i

cout<<"a=";

//inserisci il numero

cin>>a;

F<

//chiudendo il flusso

f.close();

sistema("pausa");

restituire 0;

_______________________________________________________________

Per leggere le informazioni da un file di testo, è necessario dichiarare una variabile di tipo ifstream. Successivamente, è necessario aprire il file per la lettura utilizzando l'operatore aprire. Se la variabile è chiamata F, le prime due affermazioni saranno le seguenti:

F.open("D:\\gioco\\noobs.txt", ios::in);

Dopo aver aperto un file in modalità lettura, puoi leggere le informazioni da esso allo stesso modo della tastiera, solo invece dicinspecificare il nome del flusso da cui verranno letti i dati.

Ad esempio, per leggere dal flusso F nella variabile a, l'istruzione di input sarebbe simile a questa:

Due numeri in un editor di testo sono considerati separati se è presente almeno uno dei caratteri tra di loro: spazio, tabulazione, carattere di fine riga. È bene che il programmatore sappia in anticipo quanti e quali valori memorizzare in un file di testo. Tuttavia, spesso il tipo di valori memorizzati nel file è semplicemente noto e il loro numero può variare. Per risolvere questo problema, è necessario leggere uno alla volta i valori del file e, prima di ogni lettura, verificare se è stata raggiunta la fine del file. C'è una funzione per questo F. eof().

Qui F è il nome del flusso, la funzione restituisce un valore booleano: true o false, a seconda che sia stata raggiunta la fine del file. Pertanto, un ciclo per leggere il contenuto dell'intero file può essere scritto in questo modo:

//organizza per leggere i valori da un file, esecuzione

//il ciclo si interromperà quando raggiungiamo la fine del file,

//in questo caso F.eof() restituirà true

mentre (!F.eof())

ESEMPIO:

I numeri reali sono memorizzati nel file di testo D:\\game\\noobs.txt, visualizzali sullo schermo e calcola il loro numero.

#include "stdafx.h"

#includere

#includere

#includere

#includere

usando lo spazio dei nomi std;

int principale()

setlocale(LC_ALL, "RUS");

int=0;

galleggiante a;

fstream F;

//apri il file in modalità di lettura

F.open("D:\\gioco\\noobs.txt");

//se il file è stato aperto correttamente, allora

//loop per leggere i valori da un file; l'esecuzione del ciclo verrà interrotta,

//quando raggiungiamo la fine del file, nel qual caso F.eof() restituirà true.

mentre (!F.eof())

//leggendo il valore successivo dal flusso F nella variabile a

F>>a;

//emette il valore della variabile a sullo schermo

cout<

//aumenta il numero di numeri letti

//chiudendo il flusso

f.close();

//inserimento del numero di numeri letti sullo schermo

cout<<"n="<

//se il file è stato aperto in modo errato, l'output

//messaggi sull'assenza di tale file

altrimenti cout<<" Файл не существует"<

sistema("pausa");

restituire 0;

C++. Elaborazione di file binari

Quando si scrivono informazioni su un file binario, caratteri e numeri vengono scritti come una sequenza di byte.

In modo da annotare dati in un file binario, è necessario:

    dichiarare una variabile di file di tipo FAIL * utilizzando l'istruzione FILE *nomefile;. Qui nomefile è il nome della variabile in cui verrà memorizzato il puntatore al file.

    scrivere informazioni su un file usando la funzione fwrite

In modo da pensare z dati da un file binario, è necessario:

    descrivi una variabile di tipo FILE *

    aprire il file con la funzione fopen

    chiudi il file con la funzione fclose

Funzioni di base necessarie per lavorare con i file binari.

Per scoperte file, è prevista la funzione fopen.

FILE *fopen(const *nomefile, const char *modalità)

Qui filename è una stringa che memorizza il nome completo del file che viene aperto, mode è una stringa che definisce la modalità di lavoro con il file; sono possibili i seguenti valori:

"rb" - apre il file binario in modalità di lettura;

"wb" - crea un file binario per la scrittura; se esiste, il suo contenuto viene cancellato;

"ab" - crea o apri un file binario da aggiungere alla fine del file;

"rb+" - apre un file binario esistente in modalità lettura-scrittura;

"wb+" - apre un file binario in modalità lettura-scrittura, il file esistente viene cancellato;

"ab+" - Viene aperto o creato un file binario per correggere le informazioni esistenti e aggiungere nuove informazioni alla fine del file.

La funzione restituisce il valore NULL nella variabile file f se il file non è stato aperto correttamente. Dopo che il file è stato aperto, il suo 0° byte è disponibile, il puntatore del file è 0, il cui valore viene spostato del numero di byte letti (scritti) mentre viene letto o scritto. Il valore corrente del puntatore al file è il numero di byte da cui avverrà l'operazione di lettura o scrittura.

Per chiusura file, è prevista la funzione fclose

int fclose(FILE *nomefile);

Restituisce 0 se il file è stato chiuso correttamente, NULL in caso contrario.

La funzione di rimozione è per rimozione File.

int remove(const char *nomefile);

Questa funzione rimuove un file chiamato filenema dal disco. Il file da eliminare deve essere chiuso. La funzione restituisce un valore diverso da zero se non è stato possibile eliminare il file.

Per rinominare files, la funzione di rinomina è intesa:

int rename(const char *oldfilename, const char *newfilename);

Il primo parametro è il vecchio nome del file, il secondo è quello nuovo. Restituisce 0 al completamento con successo del programma.

Lettura da un file binario viene eseguita utilizzando la funzione fread:

fread(void *ptr, dimensione, n, FILE *nomefile);

La funzione fread legge n elementi di dimensione dal file nomefile nell'array ptr. La funzione restituisce il numero di elementi letti. Dopo aver letto da un file, il suo puntatore viene spostato di n*byte di dimensione.

Registrazione in un file binario viene eseguita utilizzando la funzione fwrite:

fwrite(const void *ptr, size, n, FILE *nomefile);

La funzione fwrite scrive n elementi di dimensione dimensione nel file nomefile dall'array ptr. La funzione restituisce il numero di elementi scritti. Dopo che le informazioni sono state scritte nel file, il puntatore viene spostato di n*byte di dimensione.

Per controllo di fine file c'è una funzione feof:

int feof(FILE *nomefile);

Restituisce un valore diverso da zero se viene raggiunta la fine del file.

ESEMPIO:

Crea un file binario D:\\game\\noobs.dat e scrivici un numero intero n e n numeri reali.

#include "stdafx.h"

#includere

usando lo spazio dei nomi std;

int principale()

setlocale(LC_ALL, "RUS");

int n, i;

doppia a;

// crea un file binario in modalità di scrittura

f=fopen("D:\\gioco\\noobs.dat", "wb");

// ingresso numerin

cout<<"n="; cin>>n;

fwrite(&n, sizeof(int), 1, f);

//ciclo per inserire n numeri reali

per (i=0; i

//inserisci il numero reale successivo

cout<<"a=";

cin>>a;

//scrive il numero reale nel file binario

fwrite(&a, sizeof(doppio), 1, f);

// chiudere file

fclose(f);

sistema("pausa");

restituire 0;

ESEMPIO:

Visualizza il contenuto del file binario D:\\game\\noobs.dat creato nell'attività precedente

#include "stdafx.h"

#includere

usando lo spazio dei nomi std;

int principale()

setlocale(LC_ALL, "RUS");

int n, i;

doppia *a;

FILE *f; //descrivi la variabile del file

//apri il file binario esistente in modalità di lettura

//legge un intero dal file nella variabile n

//emette n sullo schermo

cout<<"n="<

//alloca memoria per un array di n numeri

a=nuovo doppio[n];

//leggendo n numeri reali dal file nell'array a

//emette l'array sullo schermo

per (i=0; i

cout<

cout<

// chiudere file

fclose(f);

sistema("pausa");

restituire 0;

Binario- struttura dati sequenziale, dopo l'apertura del file è disponibile il primo byte in esso memorizzato. È possibile scrivere o leggere in sequenza i dati da un file. Supponiamo di dover contare il quindicesimo numero e poi il primo. Con l'accesso seriale, questo può essere fatto nel modo seguente:

int n, i;

doppia a;

FILE *f;

f=fopen("D:\\gioco\\noobs.dat", "rb");

per (i=0; i<15; i++)

fclose(f);

f=fopen("D:\\gioco\\noobs.dat", "rb");

fread(&a, sizeof(doppio), 1, f);

fclose(f);

Come puoi vedere, leggere i numeri da un file e poi riaprire il file non è il modo più conveniente. È molto più comodo usare la funzione fseek per spostare il puntatore del file su un dato byte.

int fseek(FILE *nomefile, long int offset, int origin);

La funzione imposta il puntatore sulla posizione corrente del file F in base al valore di origine e offset offset. Il parametro offset è uguale al numero di byte di cui il puntatore al file verrà spostato rispetto all'origine specificata dal parametro origin. Il valore per il parametro origin deve essere uno dei seguenti valori per l'offset, definito nell'intestazione stdio.h:

SEEK_SET - dall'inizio del file;

SEEK_CUR - dalla posizione attuale;

SEEK_END - dalla fine del file.

La funzione restituisce zero se l'operazione ha esito positivo, diverso da zero se l'offset non riesce.

La funzione fseek implementa effettivamente l'accesso diretto a qualsiasi valore nel file. Hai solo bisogno di conoscere la posizione (numero di byte) del valore nel file. Considera l'uso dell'accesso diretto nei file binari usando l'esempio di risoluzione del problema seguente.

ESEMPIO

Nel file binario D:\\game\\noobs.dat creato in precedenza, scambia il numero reale più grande e quello più piccolo.

L'algoritmo per la risoluzione del problema consiste nei seguenti passaggi:

    leggere i reali da un file in un array a.

    cerca nell'array a i valori massimo (max) e minimo (min) e i loro numeri (imax, imin).

    spostando il puntatore del file al valore massimo e scrivendo min.

    spostando il puntatore del file sul valore minimo e scrivendo max.

Di seguito è riportato il testo del programma per risolvere il problema con i commenti.

#include "stdafx.h"

#includere

usando lo spazio dei nomi std;

int principale()

setlocale(LC_ALL, "RUS");

int n, i, imax, imin;

doppia *a, max, min;

FILE *f;

//apri il file in modalità lettura/scrittura

f=fopen("D:\\gioco\\noobs.dat", "rb+");

//legge dal file alla variabile n numero

//numeri reali nel file

fread(&n, sizeof(int), 1, f);

cout<<"n="<

//alloca memoria per memorizzare numeri reali,

//che verrà archiviato nell'array a

a=nuovo doppio[n];

//legge dal file in un array e numeri reali

fread(a, sizeof(doppio), n, f);

//cerca gli elementi massimo e minimo

//nell'array a e i loro indici

per (imax=imin=0, max=min=a, i=1; i

se (a[i]>max)

max=a[i];

se (a[i]

min=a[i];

// in movimento puntatore a massimo elemento

fseek(f, sizeof(int)+imax*sizeof(doppio), SEEK_SET);

//registrazione min invece dell'elemento massimo del file

fwrite(&min, sizeof(doppio), 1, f);

// in movimento puntatore a minimo elemento

fseek(f, sizeof(int)+imin*sizeof(doppio), SEEK_SET);

//registra il massimo invece dell'elemento minimo del file

fwrite(&max, sizeof(doppio), 1, f);

//chiudendo il file

fclose(f);

// memoria libera

eliminare[ ]un;

sistema("pausa");

tag: File di testo, fopen, fclose, feof, setbuf, setvbuf, fflush, fgetc, fprintf, fscanf, fgets, buffered stream, unbuffered stream.

Lavorare con i file di testo

Lavorare con un file di testo è simile a lavorare con la console: usando le funzioni di input formattato, salviamo i dati in un file, usando le funzioni di output formattato, leggiamo i dati da un file. Ci sono molte sfumature, che considereremo in seguito. Le principali operazioni da fare sono

  • 1. Aprire il file in modo che sia possibile accedervi. Di conseguenza, puoi aprire per leggere, scrivere, leggere e scrivere, riscrivere o scrivere fino alla fine del file, ecc. Quando apri un file, possono verificarsi anche molti errori: il file potrebbe non esistere, potrebbe non essere il tipo di file corretto, potresti non avere l'autorizzazione per lavorare sul file e così via. Tutto questo deve essere preso in considerazione.
  • 2. Lavora direttamente con il file: scrittura e lettura. Qui dobbiamo anche ricordare che non stiamo lavorando con la memoria ad accesso casuale, ma con un flusso bufferizzato, che aggiunge le sue specifiche.
  • 3. Chiudere il file. Poiché il file è una risorsa esterna rispetto al programma, se non è chiuso continuerà a rimanere sospeso in memoria, eventualmente anche dopo la chiusura del programma (ad esempio non sarà possibile eliminare un file aperto o modifiche, ecc.). Inoltre, a volte è necessario non chiudere, ma "riaprire" il file per modificare, ad esempio, la modalità di accesso.

Inoltre, ci sono una serie di attività quando non è necessario accedere al contenuto di un file: rinominare, spostare, copiare, ecc. Sfortunatamente, nello standard C non c'è una descrizione delle funzioni per queste esigenze. Esistono certamente per ciascuna delle implementazioni del compilatore. Leggere il contenuto di una directory (cartella, directory) significa anche accedere a un file, perché la cartella stessa è un file con metainformazioni.

A volte è necessario eseguire alcune operazioni ausiliarie: spostarsi nella posizione desiderata nel file, ricordare la posizione corrente, determinare la lunghezza del file e così via.

Per lavorare con un file, è richiesto un oggetto FILE. Questo oggetto memorizza un identificatore del flusso di file e le informazioni necessarie per gestirlo, incluso un puntatore al relativo buffer, un indicatore di posizione del file e indicatori di stato.

L'oggetto FILE stesso è una struttura, ma non è possibile accedere ai suoi campi. Un programma portatile deve trattare un file come un oggetto astratto che consente l'accesso al flusso di file.

La creazione e l'allocazione della memoria per un oggetto di tipo FILE viene eseguita utilizzando le funzioni fopen o tmpfile (ce ne sono altre, ma ci concentreremo solo su queste).

La funzione fopen apre un file. Richiede due argomenti: una stringa con l'indirizzo del file e una stringa con la modalità di accesso del file. Il nome del file può essere assoluto o relativo. fopen restituisce un puntatore a un oggetto FILE, che può quindi essere utilizzato per accedere al file.

FILE* fopen(const char* nome file, const char* modalità);

Ad esempio, apriamo un file e ci scriviamo Hello World

#includere #includere #includere void main() ( //Utilizzando la variabile file, accederemo al file FILE *file; //Apri un file di testo con permessi di scrittura file = fopen("C:/c/test.txt", "w+t" ) ; //Scrivi nel file fprintf(file, "Hello, World!"); //Chiudi il file fclose(file); getch(); )

La stessa funzione fopen alloca memoria per l'oggetto, la pulizia viene eseguita dalla funzione fclose. Devi chiudere il file, non si chiuderà da solo.

La funzione fopen può aprire un file in modalità testo o binaria. L'impostazione predefinita è il testo. La modalità di accesso può essere la seguente

Opzioni di accesso ai file.
Tipo Descrizione
R Lettura. Il file deve esistere.
w Scrivere un nuovo file. Se esiste già un file con lo stesso nome, il suo contenuto andrà perso.
un Scrivi alla fine del file. Le operazioni di posizionamento (fseek, fsetpos, frewind) vengono ignorate. Il file viene creato se non esiste.
r+ Lettura e aggiornamento. Puoi sia leggere che scrivere. Il file deve esistere.
w+ Registrazione e aggiornamento. Viene creato un nuovo file. Se esiste già un file con lo stesso nome, il suo contenuto andrà perso. Puoi sia scrivere che leggere.
a+ Scrivi fino alla fine e aggiorna. Le operazioni di posizionamento sono di sola lettura, quelle di sola scrittura vengono ignorate. Se il file non esiste, ne verrà creato uno nuovo.

Se devi aprire un file in modalità binaria, la lettera b viene aggiunta alla fine della riga, ad esempio “rb”, “wb”, “ab” o, per la modalità mista, “ab+”, “wb+ ”, “ab+”. Invece di b, puoi aggiungere la lettera t, quindi il file si aprirà in modalità testo. Dipende dall'implementazione. Nel nuovo standard C (2011), la lettera x significa che la funzione fopen dovrebbe fallire se il file esiste già. Integriamo il nostro vecchio programma: riapri il file e considera che l'abbiamo scritto lì.

#includere #includere #includere void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); fclose(file); file = fopen("C:/c/test.txt", "r"); fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch(); )

Potresti usare fscanf invece di fgets, ma ricorda che può leggere solo una stringa fino al primo spazio.
fscanf(file, "%127s", buffer);

Inoltre, invece di aprire e chiudere il file, puoi utilizzare la funzione freopen, che "riapre" il file con nuove autorizzazioni.

#includere #includere #includere void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); freopen("C:/ c/test.txt", "r", file); fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch(); )

Le funzioni fprintf e fscanf differiscono da printf e scanf solo per il fatto che prendono come primo argomento un puntatore a un FILE a cui emetteranno o da cui leggeranno i dati. Qui vale la pena aggiungere subito che le funzioni printf e scanf possono essere facilmente sostituite dalle funzioni fprintf e fscanf. Nel sistema operativo (consideriamo i sistemi operativi più comuni e adeguati), ci sono tre flussi standard: standard output stdout, standard input stdin e standard error stderr. Vengono aperti automaticamente durante l'avvio dell'applicazione e sono associati alla console. Esempio

#includere #includere #includere void main() ( int a, b; fprintf(stdout, "Inserisci due numeri\n"); fscanf(stdin, "%d", &a); fscanf(stdin, "%d", &b); if (b == 0) ( fprintf(stderr, "Errore: dividere per zero"); ) else ( fprintf(stdout, "%.3f", (float) a / (float) b); ) getch(); )

Errore di apertura del file

Se la chiamata alla funzione fopen fallisce, restituirà NULL. Gli errori durante il lavoro con i file sono abbastanza comuni, quindi ogni volta che apriamo un file, dobbiamo controllare il risultato del lavoro

#includere #includere #includere #define ERROR_OPEN_FILE -3 void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); if (file == NULL) ( printf("Errore di apertura file"); getch(); exit(ERROR_OPEN_FILE); ) fprintf(file, "Hello, World!"); freopen("C:/c/test.txt", "r", file); if (file = = NULL) ( printf("Errore nell'apertura del file"); getch(); exit(ERROR_OPEN_FILE); ) fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch() ; )

Il problema è causato dal caso in cui vengono aperti più file contemporaneamente: se uno di essi non può essere aperto, anche il resto deve essere chiuso

FILE *file di input, *file di output; m senza segno, n; i, j senza segno; inputFile = fopen(INPUT_FILE, SOLO LETTURA); if (inputFile == NULL) ( printf("Errore nell'apertura del file %s", INPUT_FILE); getch(); exit(3); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Errore nell'apertura del file %s", OUTPUT_FILE); getch(); if (inputFile != NULL) ( fclose(inputFile); ) exit(4); ) ...

In casi semplici si può agire di lato, come nel codice precedente. Nei casi più complessi vengono utilizzati metodi che sostituiscono RAII da C++: wrapper o funzionalità del compilatore (pulizia in GCC), ecc.

Bufferizzazione dei dati

Come accennato in precedenza, quando emettiamo i dati, questi vengono prima memorizzati nel buffer. Il buffer viene cancellato

  • 1) Se è pieno
  • 2) Se il flusso si chiude
  • 3) Se indichiamo esplicitamente che è necessario cancellare il buffer (ci sono eccezioni anche qui :)).
  • 4) Cancellato anche se il programma è stato completato con successo. Allo stesso tempo, tutti i file vengono chiusi. In caso di errore di runtime, ciò potrebbe non verificarsi.

È possibile forzare lo scaricamento del buffer chiamando la funzione fflush(File *). Considera due esempi: con pulizia e senza.

#includere #includere #includere void main() ( FILE *file; char c; file = fopen("C:/c/test.txt", "w"); do ( c = getch(); fprintf(file, "%c", c ); fprintf(stdout, "%c", c); //fflush(file); ) while(c != "q"); fclose(file); getch(); )

Decommenta la chiamata a fflush. In fase di esecuzione, apri il file di testo e osserva il comportamento.

Puoi assegnare tu stesso un buffer di file impostando la tua dimensione. Questo viene fatto usando la funzione

void setbuf(FILE*stream, char*buffer);

che prende un FILE già aperto e un puntatore a un nuovo buffer. La dimensione del nuovo buffer deve essere almeno BUFSIZ (ad esempio, sulla workstation corrente, BUFSIZ è 512 byte). Se si passa NULL come buffer, il flusso verrà annullato. Puoi anche usare la funzione

int setvbuf(FILE*stream, char*buffer, int mode, size_t size);

che richiede un buffer di dimensioni arbitrarie. la modalità può assumere i seguenti valori

  • _IOFBF- buffering completo. I dati vengono scritti nel file quando è pieno. In una lettura, il buffer viene considerato pieno quando viene richiesta un'operazione di input e il buffer è vuoto.
  • _IOLBF- buffering lineare. I dati vengono scritti nel file quando si riempie o quando viene rilevato un carattere di nuova riga. In una lettura, il buffer viene riempito fino al carattere di nuova riga quando viene richiesta un'operazione di input e il buffer è vuoto.
  • _IONBF- nessun buffering. In questo caso, i parametri size e buffer vengono ignorati.
In caso di successo, la funzione restituisce 0.

Esempio: impostiamo il nostro buffer e vediamo come viene eseguita la lettura da un file. Lascia che il file sia breve (qualcosa come Hello, World!) e lo leggiamo carattere per carattere

#includere #includere #includere void main() ( FILE *input = NULL; char c; char buffer = (0); input = fopen("D:/c/text.txt", "rt"); setbuf(input, buffer); while ( !feof(input)) ( c = fgetc(input); printf("%c\n", c); printf("%s\n", buffer); _getch(); ) fclose(input); )

Si può vedere che i dati sono già nel buffer. La lettura carattere per carattere è già stata eseguita dal buffer.

fef

funzione int feof(FILE*stream); restituisce true se è stata raggiunta la fine del file. La funzione è comoda da usare quando è necessario scorrere l'intero file dall'inizio alla fine. Lascia che ci sia un file con contenuto di testo text.txt. Leggiamo il file carattere per carattere e lo visualizziamo sullo schermo.

#includere #includere #includere void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Errore nell'apertura del file") ; _getch(); exit(0); ) while (!feof(input)) ( c = fgetc(input); fprintf(stdout, "%c", c); ) fclose(input); _getch(); )

Andrebbe tutto bene, solo la funzione feof non funziona correttamente... Ciò è dovuto al fatto che il concetto di "fine file" non è definito. Quando si utilizza feof, si verifica un errore comune quando l'ultimo dato letto viene stampato due volte. Ciò è dovuto al fatto che i dati vengono scritti nel buffer di input, l'ultima lettura si verifica con un errore e la funzione restituisce il vecchio valore di lettura.

#includere #includere #includere void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Errore nell'apertura del file") ; _getch(); exit(0); ) while (!feof(input)) ( fscanf(input, "%c", &c); fprintf(stdout, "%c", c); ) fclose(input); _get(); )

Questo esempio avrà esito negativo (molto probabilmente) e stamperà l'ultimo carattere del file due volte.

La soluzione è non usare feof. Ad esempio, memorizzare il numero totale di voci o utilizzare il fatto che le funzioni fscanf, ecc. di solito restituiscono il numero di valori letti correttamente e abbinati.

#includere #includere #includere void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Errore nell'apertura del file") ; _getch(); exit(0); ) while (fscanf(input, "%c", &c) == 1) ( fprintf(stdout, "%c", c); ) fclose(input); _getch() ; )

Esempi

1. Due numeri sono scritti in un file: le dimensioni dell'array. Riempiamo il secondo file con una matrice di numeri casuali.

#includere #includere #includere #includere //Nomi file e permessi #define FILE_INPUT "D:/c/input.txt" #define FILE_OUTPUT "D:/c/output.txt" #define READ_ONLY "r" #define WRITE_ONLY "w" //Valore massimo per l'array size #define MAX_DIMENSION 100 //Errore durante l'apertura del file #define ERROR_OPEN_FILE -3 void main() ( FILE *inputFile, *outputFile; unsigned m, n; unsigned i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if ( inputFile = = NULL) ( printf("Errore nell'apertura del file %s", INPUT_FILE); getch(); exit(ERROR_OPEN_FILE); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Errore nell'apertura del file %s", OUTPUT_FILE); getch(); //Se il file è stato aperto correttamente per la lettura, deve essere chiuso if (inputFile != NULL) ( fclose(inputFile); ) exit(ERROR_OPEN_FILE); ) fscanf(inputFile , "%ud %ud", &m, &n); if (m > MAX_DIMENSION) ( m = MAX_DIMENSION; ) if (n > MAX_DIMENSION) ( n = MAX_DIMENSION; ) srand(time(NULL)); for (i = 0 ; io< n; i++) { for (j = 0; j < m; j++) { fprintf(outputFile, "%8d ", rand()); } fprintf(outputFile, "\n"); } //Закрываем файлы fclose(inputFile); fclose(outputFile); }

2. L'utente copia il file, scegliendo prima la modalità di funzionamento: il file può essere inviato sia alla console che copiato in un nuovo file.

#includere #includere #includere #define ERROR_FILE_OPEN -3 void main() ( FILE *origin = NULL; FILE *output = NULL; char filename; int mode; printf("Enter filename: "); scanf("%1023s", filename); origin = fopen (nome file, "r"); if (origine == NULL) ( printf("Errore durante l'apertura del file %s", nome file); getch(); exit(ERROR_FILE_OPEN); ) printf("entra in modalità: "); scanf( "%d", &mode); if (mode == 1) ( printf("Enter filename: "); scanf("%1023s", filename); output = fopen(filename, "w"); if (output = = NULL) ( printf("Errore durante l'apertura del file %s", nomefile); getch(); fclose(origine); exit(ERROR_FILE_OPEN); ) ) else ( output = stdout; ) while (!feof(origine)) ( fprintf (output, "%c", fgetc(origine)); ) fclose(origine); fclose(output); getch(); )

3. L'utente inserisce i dati dalla console e questi vengono scritti in un file finché non viene premuto il tasto esc. Controllare il programma e vedere. come si comporta se si digita backspace: cosa viene restituito a un file e cosa viene inviato alla console.

#includere #includere #includere #define ERROR_FILE_OPEN -3 void main() ( FILE *output = NULL; char c; output = fopen("D:/c/test_output.txt", "w+t"); if (output == NULL) ( printf ("Errore nell'apertura del file"); _getch(); exit(ERROR_FILE_OPEN); ) for (;;) ( c = _getch(); if (c == 27) ( break; ) fputc(c, output); fputc( c, stdout); ) fclose(output); )

4. Il file contiene numeri interi. Trova il massimo di loro. Sfruttiamo il fatto che la funzione fscanf restituisce il numero di oggetti letti correttamente e abbinati. Il numero 1 deve essere restituito ogni volta.

#includere #includere #includere #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Errore nell'apertura del file"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; hasRead = 1; while (hasRead == 1) ( hasRead = fscanf(input, "%d", &num); if (hasRead != 1) ( continua; ) if (num >

Un'altra soluzione è leggere i numeri fino a raggiungere la fine del file.

#includere #includere #includere #includere #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Errore nell'apertura del file"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; while (!feof(input)) ( fscanf(input, "%d", &num); if (num > maxn ) ( maxn = num; ) ) printf("numero massimo = %d", maxn); fclose(input); _getch(); )

5. Il file contiene parole: parola russa, tabulazione, parola inglese, in più righe. L'utente inserisce una parola inglese, è necessario visualizzare quella russa.

Il file di traduzione è simile a questo

sole sole
penna a matita
matita penna a sfera
porta
finestra di Windows
sedia
poltrona

e salvato nella codifica cp866 (OEM 866). È importante qui: anche l'ultima coppia di parole termina con una nuova riga.

L'algoritmo è il seguente: leggiamo una riga dal file, troviamo una scheda nella riga, sostituiamo la scheda con zero, copiamo la parola russa dal buffer, copiamo la parola inglese dal buffer, controlliamo l'uguaglianza.

#includere #includere #includere #includere #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; char buffer; char enWord; char ruWord; char usrWord; unsigned index; int length; int wasFound; input = fopen("D:/c/input.txt ", "r"); if (input == NULL) ( printf("Errore nell'apertura del file"); _getch(); exit(ERROR_FILE_OPEN); ) printf("inserisci parola: "); fgets(usrWord, 127, stdin ); wasFound = 0; while (!feof(input)) ( fgets(buffer, 511, input); length = strlen(buffer); for (index = 0; index< length; index++) { if (buffer == "\t") { buffer = "\0"; break; } } strcpy(ruWord, buffer); strcpy(enWord, &buffer); if (!strcmp(enWord, usrWord)) { wasFound = 1; break; } } if (wasFound) { printf("%s", ruWord); } else { printf("Word not found"); } fclose(input); _getch(); }

6. Contare il numero di righe nel file. Leggeremo il file carattere per carattere, contando il numero di "\n" caratteri finché non incontreremo il carattere EOF. EOF è un carattere speciale che indica che l'input è terminato e non ci sono più dati da leggere. La funzione restituisce un valore negativo in caso di errore.
NOTA: EOF è di tipo int, quindi è necessario utilizzare int per leggere i caratteri. Inoltre, il valore di EOF non è definito dallo standard.

#define _CRT_SECURE_NO_WARNINGS #includi #includere #includere int cntLines(const char *filename) ( int lines = 0; int any; //any di tipo int perché EOF è di tipo int! FILE *f = fopen(filename, "r"); if (f == NULL) ( return -1; ) do ( any = fgetc(f); //printf("%c", any);//debug if (any == "\n") ( lines++; ) ) while(any != EOF); ​​​​fclose(f); righe di ritorno; ) void main() ( printf("%d\n", cntLines("C:/c/file.txt")); _getch(); )

Ru-Cyrl 18-tutorial Sypachev SS 14-04-1989 [email protetta] Stepan Sypachev studenti

Non è ancora chiaro? - scrivi le domande nella casella

Articoli correlati in alto