====== Είσοδος και έξοδος αρχείων ====== Η //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. #include #include using namespace std; int main() { ofstream myfile; myfile.open ("hello.txt"); myfile << "Hello World!"; myfile.close(); } ===== Άνοιγμα αρχείου για ανάγνωση και εγγραφή ===== Το άνοιγμα των αρχείων γίνεται μέσω της μεθόδου //open// η οποία προδιαγράφεται παρακάτω: void open (const char* filename, ios_base::openmode mode); Η παράμετρος //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** | Εάν το αρχείο υπάρχει ήδη και έχει περιεχόμενο, το υφιστάμενο περιεχόμενο διαγράφεται. | Οι παραπάνω τιμές μπορούν να συνδυαστούν ως εξής: 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); === Default τιμές === Οι //default// τιμές της παραμέτρου //mode// για τις παραπάνω κλάσεις κλάσεις έχουν ως εξής: ^ Κλάση ^ Τιμή ^ Παρατήρηση ^ | **ofstream** | **ios::out** | Η τιμή ισχύει ακόμη και εάν αλλάξετε την παράμετρο //mode// | | **ifstream** | **ios::in** | Η τιμή ισχύει ακόμη και εάν αλλάξετε την παράμετρο //mode// | | **fstream** | **ios::in %%|%% ios::out** | Η τιμή δεν ισχύει εάν αλλάξετε την παράμετρο //mode//. Μπορείτε να επαναορίσετε τις τιμές | Παρατηρήστε ότι η μέθοδος //open// δεν έχει επιστρεφόμενη τιμή για να ελέγξουμε την αποτυχία, ούτε παράγει κάποιο //exception//. Για να ελέγξετε εάν ένα αρχείο έχει ανοίξει σωστά για διάβασμα ή γράψιμο μπορείτε να χρησιμοποιήσετε τη μέθοδο //is_open()// ως εξής: ofstream lena("lena.png", ios::out | ios::trunc | ios::binary); if (!lena.is_open()) { cerr << "Error while opening \"lena.png\" for writting\n"; } Παρατηρήστε ότι στο παραπάνω παράδειγμα χρησιμοποιούμε τον κατασκευαστή της κλάσης //ofstream// αντί για τη μέθοδο //open//. Τα ορίσματα που λαμβάνει ο κατασκευαστής και η σειρά τους είναι ταυτόσημα με αυτά της μεθόδου //open//. ===== Κλείσιμο αρχείου ===== Για να κλείσετε το αρχείο που προηγουμένως ανοίξατε με τη μέθοδο //open// αρκεί να καλέσετε τη μέθοδο //close// ως εξής: lena.close(); ===== Αρχεία κειμένου ===== //Streams// κειμένου είναι εκείνα τα streams που κατά το άνοιγμα του αρχείου δεν έχουν ορισμένο το //flag **ios::binary**//. Τα αρχεία αυτά υποθέτουμε ότι περιέχουν μόνο εκτυπώσιμους χαρακτήρες (δηλ. κείμενο) και κατ' επέκταση μπορούμε να τα διαβάσουμε υποθέτοντας ότι οι λέξεις χωρίζονται μεταξύ τους από κενό χαρακτήρα ή χαρακτήρα αλλαγής γραμμής (''' ','\t','\n','\x0B','\f','\r''') και οι γραμμές χωρίζονται με χαρακτήρα αλλαγής γραμμής ('''\r','\n'''). Ο τρόπος με τον οποίο γράφετε ή διαβάζετε είναι ο τρόπος που το κάνετε για τη βασική είσοδο και έξοδο. ^ Γράψιμο σε αρχείο κειμένου ^ | #include #include 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(); } | ^ Διάβασμα από αρχείο κειμένου γραμμή-γραμμή ^ Διάβασμα από αρχείο κειμένου λέξη-λέξη και εκτύπωση κάθε λέξης σε νέα γραμμή ^ | #include #include #include 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(); } | #include #include #include 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(); } | ===== Δυαδικά αρχεία ===== Για δυαδικά αρχεία η ανάγνωση και η εγγραφή με χρήση των τελεστών %%<<%% (//extraction operator//) και %%>>%% (//insertion operator//) δεν είναι εφικτή. Για τον λόγο αυτό τα //file streams// περιέχουν δύο μεθόδους για διάβασμα και γράψιμο δυαδικής πληροφορίας. | istream& read (char* s, streamsize n); | Διάβασμα //n// στοιχείων τύπου //char// από το //stream// και αποθήκευση στο //s//. Η συνάρτηση επιστρέφει μία αναφορά στο υφιστάμενο stream. Σε περίπτωση που δεν υπάρχουν //n// διαθέσιμα bytes στο //stream// αντιγράφει στο //s// όσα είναι διαθέσιμα και θέτει τα //flags// **failbit** και **eofbit**. Ο αριθμός των bytes που διαβάστηκαν επιστρέφεται από τη συνάρτηση [[http://www.cplusplus.com/reference/istream/istream/gcount/|gcount]]. | | ostream& write (const char* s, streamsize n); | Γράψιμο //n// στοιχείων τύπου //char// από το //s// προς το //stream//. | Δείτε το παρακάτω παράδειγμα ανάγνωσης και εγγραφής από δυαδικό αρχείο. Το πρόγραμμα αντιγράφει το περιεχόμενο ενός υφιστάμενου αρχείου σε ένα άλλο σε τμήματα των SIZE bytes. #include #include #include 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(); }