cpp:file_io

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
cpp:file_io [2020/05/17 18:17]
cpp:file_io [2020/05/17 19:17]
gthanos
Line 1: Line 1:
 +====== Είσοδος και έξοδος αρχείων ======
 +
 +Η //standard// βιβλιοθήκη της C++ παρέχει τις παρακάτω κλάσεις για είσοδο και έξοδο από αρχεία. 
 +  - **[[http://www.cplusplus.com/reference/fstream/ifstream/|ifstream]]:** Κλάση για διάβασμα από αρχείο.
 +  - **[[http://www.cplusplus.com/reference/fstream/ofstream/|ofstream]]:** Κλάση για γράψιμο σε αρχείο.
 +  - **[[http://www.cplusplus.com/reference/fstream/fstream/|fstream]]:** Κλάση για διάβασμα και γράψιμο σε αρχείο.
 +
 +Οι παραπάνω κλάσεις είναι απόγονοι των κλάσεων //[[http://www.cplusplus.com/reference/istream/istream/|istream]]// και //[[http://www.cplusplus.com/reference/ostream/ostream/|ostream]]//. Η χρήση των παραπάνω κλάσεων είναι ανάλογη με τις κλάσεις [[cpp:basic_io#stdcin|std::cin]] και [[cpp:basic_io#stdcout|std::cout]] που επίσης είναι απόγονοι των κλάσεων //istream// και //ostream//. Δείτε ενδεικτικά, το παρακάτω παράδειγμα γραφής στο αρχείο hello.txt.
 +
 +<code cpp hello_file.cpp>
 +#include <iostream>
 +#include <fstream>
 +using namespace std;
 +
 +int main() {
 +  ofstream myfile;
 +  myfile.open ("hello.txt");
 +  myfile << "Hello World!";
 +  myfile.close();
 +}
 +</code>
 +
 +===== Άνοιγμα αρχείου για ανάγνωση και εγγραφή =====
 +
 +Το άνοιγμα των αρχείων γίνεται μέσω της μεθόδου //open// η οποία προδιαγράφεται παρακάτω:
 +<code cpp>
 +void open (const char* filename, ios_base::openmode mode);
 +</code>
 +
 +Η παράμετρος //filename// είναι ένα αλφαριθμητικό που περιγράφει το σχετικό ή απόλυτο path προς το αρχείο. Η παράμετρος //mode// μπορεί να πάρει τις ακόλουθες τιμές ή συνδυασμούς τους:
 +
 +^  Τιμή  ^  Επεξήγηση  ^
 +|  **ios::in**   | Άνοιγμα για ανάγνωση από το αρχείο. |
 +|  **ios::out**  | Άνοιγμα για εγγραφή στο αρχείο. |
 +|  **ios::binary**  | Άνοιγμα για ανάγνωση ή εγγραφή σε δυαδική μορφή.  |
 +|  **ios::app**  | Η θέση εγγραφής τίθεται στο τέλος του αρχείου. Εάν επιχειρήσετε να μεταβάλλετε τη θέση εγγραφής μέσω της συνάρτησης [[cpp:stream_random_io#μεταβολή_της_θέσης_ανάγνωσης_ή_εγγραφής|seekp]] __αυτό δεν θα έχει αποτέλεσμα__. |
 +|  **ios::ate**  | Θέτει τη θέση εγγραφής στο τέλος του αρχείου. Εάν δεν προσδιοριστεί το συγκεκριμένο //flag// η θέση εγγραφής τίθεται στην αρχή. Μπορείτε να μεταβάλλετε τη θέση εγγραφής μέσω της συνάρτησης [[cpp:stream_random_io#μεταβολή_της_θέσης_ανάγνωσης_ή_εγγραφής|seekp]] |
 +|  **ios::trunc**  | Εάν το αρχείο υπάρχει ήδη και έχει περιεχόμενο, το υφιστάμενο περιεχόμενο διαγράφεται. |
 +
 +Οι παραπάνω τιμές μπορούν να συνδυαστούν ως εξής:
 +<code cpp>
 +ofstream lena;
 +// Open lena.png for writing in binary mode. 
 +// Truncate file contents if file previously exists.
 +lena.open("lena.png", ios::out | ios::trunc | ios::binary);
 +</code>
 +
 +=== Default τιμές ===
 +
 +Οι //default// τιμές της παραμέτρου //mode// για τις παραπάνω κλάσεις κλάσεις έχουν ως εξής:
 +
 +^  Κλάση  ^  Τιμή  ^  Παρατήρηση  ^
 +|  **ofstream**  |  **ios::out**  | Η τιμή ισχύει ακόμη και εάν αλλάξετε την παράμετρο //mode// |
 +|  **ifstream**  |  **ios::in**  | Η τιμή ισχύει ακόμη και εάν αλλάξετε την παράμετρο //mode// |
 +|  **fstream**  |  **ios::in %%|%% ios::out**  | Η τιμή δεν ισχύει εάν αλλάξετε την παράμετρο //mode//. Μπορείτε να επαναορίσετε τις τιμές |
 +
 +Παρατηρήστε ότι η μέθοδος //open// δεν έχει επιστρεφόμενη τιμή για να ελέγξουμε την αποτυχία, ούτε παράγει κάποιο //exception//. Για να ελέγξετε εάν ένα αρχείο έχει ανοίξει σωστά για διάβασμα ή γράψιμο μπορείτε να χρησιμοποιήσετε τη μέθοδο //is_open()// ως εξής:
 +<code cpp>
 +ofstream lena("lena.png", ios::out | ios::trunc | ios::binary);
 +if (!lena.is_open()) { cerr << "Error while opening \"lena.png\" for writting\n"; }
 +</code>
 +
 +<WRAP center round tip 80%>
 +Παρατηρήστε ότι στο παραπάνω παράδειγμα χρησιμοποιούμε τον κατασκευαστή της κλάσης //ofstream// αντί για τη μέθοδο //open//. Τα ορίσματα που λαμβάνει ο κατασκευαστής και η σειρά τους είναι ταυτόσημα με αυτά της μεθόδου //open//.
 +</WRAP>
 +
 +===== Κλείσιμο αρχείου =====
 +
 +Για να κλείσετε το αρχείο που προηγουμένως ανοίξατε με τη μέθοδο //open// αρκεί να καλέσετε τη μέθοδο //close// ως εξής:
 +<code cpp>
 +lena.close();
 +</code>
 +
 +===== Αρχεία κειμένου =====
 +
 +//Streams// κειμένου είναι εκείνα τα streams που κατά το άνοιγμα του αρχείου δεν έχουν ορισμένο το //flag **ios::binary**//. Τα αρχεία αυτά υποθέτουμε ότι περιέχουν μόνο εκτυπώσιμους χαρακτήρες (δηλ. κείμενο) και κατ' επέκταση μπορούμε να τα διαβάσουμε υποθέτοντας ότι οι λέξεις χωρίζονται μεταξύ τους από κενό χαρακτήρα ή χαρακτήρα αλλαγής γραμμής (''' ','\t','\n','\x0B','\f','\r''') και οι γραμμές χωρίζονται με χαρακτήρα αλλαγής γραμμής ('''\r','\n''').
 +
 +Ο τρόπος με τον οποίο γράφετε ή διαβάζετε είναι ο τρόπος που το κάνετε για τη βασική είσοδο και έξοδο.
 +^  Γράψιμο σε αρχείο κειμένου  ^  
 +|<code cpp file_write.cpp>
 +#include <iostream>
 +#include <fstream>
 +using namespace std;
 +
 +int main (int argc, char *argv[]) {
 +  string filename;
 +  cout << "Enter output filename: ";
 +  cin >> filename;
 +  ofstream myfile (filename.c_str());
 +  if (!myfile.is_open()) {
 +    cout << "Unable to open file " << filename;
 +    return -1;    
 +  }
 +  myfile << "- Which OO language do you prefer?.\n";
 +  myfile << "- My favorite is C++.\n";
 +  myfile << "- I prefer Java and Python.\n";
 +  myfile.close();
 +}
 +</code>|
 +
 +^ Διάβασμα από αρχείο κειμένου γραμμή-γραμμή ^ Διάβασμα από αρχείο κειμένου λέξη-λέξη και εκτύπωση κάθε λέξης σε νέα γραμμή ^
 +|<code cpp file_read_line_by_line.cpp>
 +#include <iostream>
 +#include <fstream>
 +#include <string>
 +using namespace std;
 +
 +#define MAX_LINE_LEN 1024 // really big!
 +
 +int main () {
 +  string filename;
 +  cout << "Enter input filename: ";
 +  cin >> filename;
 +  ifstream myfile (filename.c_str());
 +  char line[MAX_LINE_LEN]; 
 +  
 +  if (!myfile.is_open()) {
 +    cout << "Unable to open file " << filename;
 +    return -1;    
 +  }
 +  while ( myfile.getline (line, MAX_LINE_LEN) )
 +    cout << line << '\n';   
 +  myfile.close();  
 +}
 +</code>|<code cpp file_read_word_by_word.cpp>
 +#include <iostream>
 +#include <fstream>
 +#include <string>
 +using namespace std;
 +
 +int main () {
 +  string filename, word;
 +  cout << "Enter input filename: ";
 +  cin >> filename;
 +  ifstream myfile (filename.c_str());
 +  
 +  if (!myfile.is_open()) {
 +    cout << "Unable to open file " << filename;
 +    return -1;    
 +  }
 +  while ( !myfile.eof() )  {
 +    myfile >> word;
 +    cout << word << endl; 
 +  }
 +  myfile.close();
 +      
 +}
 +</code>|
 +
 +===== Δυαδικά αρχεία =====
 +
 +Για δυαδικά αρχεία η ανάγνωση και η εγγραφή με χρήση των τελεστών %%<<%% (//extraction operator//) και %%>>%% (//insertion operator//) δεν είναι εφικτή. Για τον λόγο αυτό τα //file streams// περιέχουν δύο μεθόδους για διάβασμα και γράψιμο δυαδικής πληροφορίας.
 +
 +|  <code cpp>istream& read (char* s, streamsize n);</code>  | Διάβασμα //n// στοιχείων τύπου //char// από το //stream// και αποθήκευση στο //s//. Η συνάρτηση επιστρέφει μία αναφορά στο υφιστάμενο stream. Σε περίπτωση που δεν υπάρχουν //n// διαθέσιμα bytes στο //stream// αντιγράφει στο //s// όσα είναι διαθέσιμα και θέτει τα //flags// **failbit** και **eofbit**. Ο αριθμός των bytes που διαβάστηκαν επιστρέφεται από τη συνάρτηση [[http://www.cplusplus.com/reference/istream/istream/gcount/|gcount]].  |
 +|  <code cpp>ostream& write (const char* s, streamsize n);</code>  | Γράψιμο //n// στοιχείων τύπου //char// από το //s// προς το //stream//. |
 +
 +Δείτε το παρακάτω παράδειγμα ανάγνωσης και εγγραφής από δυαδικό αρχείο. Το πρόγραμμα αντιγράφει το περιεχόμενο ενός υφιστάμενου αρχείου σε ένα άλλο σε τμήματα των SIZE bytes.
 +
 +<code cpp binary_copy.cpp>
 +#include <iostream>
 +#include <fstream>
 +#include <cmath>
 +using namespace std;
 +
 +#define SIZE 512
 + 
 +int main (int argc, char *argv[]) {  
 +  string filename;
 +  cout << "Enter input filename: ";
 +  cin >> filename;
 +  ifstream infile(filename.c_str());
 +  if (!infile.is_open()) {
 +    cout << "[Read] Unable to open " << filename;
 +    return -1;    
 +  }
 +  
 +  cout << "Enter output filename: ";
 +  cin >> filename;
 +  ofstream outfile(filename.c_str(), ios::trunc);
 +  if (!outfile.is_open()) {
 +    cout << "[Write] Unable to open " << filename;
 +    return -1;    
 +  }
 +  
 +  char buf[SIZE];  
 +  while(!infile.eof()) {
 +    infile.read(buf, SIZE);    
 +    outfile.write(buf, infile.gcount());
 +  }
 +  infile.close();
 +  outfile.close();
 +}
 +</code>
 +
  
cpp/file_io.txt · Last modified: 2020/05/17 18:17 (external edit)