User Tools

Site Tools


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
Next revision
Previous revision
Next revision Both sides next revision
cpp:file_io [2017/05/09 10:02]
gthanos [Δυαδικά αρχεία]
cpp:file_io [2019/05/22 07:12]
gthanos [Άνοιγμα αρχείου για ανάγνωση και εγγραφή]
Line 1: Line 1:
-====== Η έννοια του stream ====== 
- 
-Η C++ εισάγει την έννοια του //stream//, ως μία σειρά από χαρακτήρες οι οποίοι μπορούν: 
-  * να γραφούν σε ένα αρχείο ή σε μία σειριακή συσκευή με τη σειρά που αυτοί εγγράφονται στο //stream//. 
-  * να διαβαστούν από ένα αρχείο ή από μία σειριακή συσκευή με τη σειρά που είναι αποθηκευμένοι ή με τη σειρά που εισήχθησαν στη συσκευή. 
- 
-Βασικά χαρακτηριστικά των //streams// είναι τα εξής: 
-  - Ένα //stream// μεταφράζεται πάντα σε μία ακολουθία χαρακτήρων. Τα //streams// δίνουν ένα ενιαίο //interface// προς τα αντικείμενα για οποιοδήποτε μέσω αποθήκευσης. Εάν μία κλάση μπορεί να γράψει σε ένα //stream// τότε μπορεί να γράψει σε όλα τα πιθανά //streams//. 
-  - Τα //streams// δουλεύουν αυτόματα με τους βασικούς τύπους δεδομένων. Για τους αναφορικούς τύπους μπορείτε να υπερφορτώσετε τους τελεστές %%>>%% και %%<<%% για είσοδο από το //stream// και έξοδο προς το //stream// αντίστοιχα. Η χρήση των τελεστών %%>>%% και %%<<%% απλοποιεί εξαιρετικά τον τρόπο με τον οποίο αλληλεπιδρούν τα προγράμματα με τα //streams//. 
- 
 ====== Είσοδος και έξοδος αρχείων ====== ====== Είσοδος και έξοδος αρχείων ======
  
 Η C++ παρέχει τις παρακάτω κλάσεις για είσοδο και έξοδο από αρχεία.  Η C++ παρέχει τις παρακάτω κλάσεις για είσοδο και έξοδο από αρχεία. 
-  - **ifstream:** Κλάση για διάβασμα από αρχείο. +  - **[[http://www.cplusplus.com/reference/fstream/ifstream/|ifstream]]:** Κλάση για διάβασμα από αρχείο. 
-  - **ofstream:** Κλάση για γράψιμο σε αρχείο. +  - **[[http://www.cplusplus.com/reference/fstream/ofstream/|ofstream]]:** Κλάση για γράψιμο σε αρχείο. 
-  - **fstream:** Κλάση για διάβασμα και γράψιμο σε αρχείο.+  - **[[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.+Οι παραπάνω κλάσεις είναι απόγονοι των κλάσεων //[[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> <code cpp hello_file.cpp>
Line 31: Line 21:
 </code> </code>
  
-===== Άνοιγμα αρχείου =====+===== Άνοιγμα αρχείου για ανάγνωση και εγγραφή =====
  
 Το άνοιγμα των αρχείων γίνεται μέσω της μεθόδου //open// η οποία προδιαγράφεται παρακάτω: Το άνοιγμα των αρχείων γίνεται μέσω της μεθόδου //open// η οποία προδιαγράφεται παρακάτω:
Line 41: Line 31:
  
 ^  Τιμή  ^  Επεξήγηση  ^ ^  Τιμή  ^  Επεξήγηση  ^
-|  **ios::in**   | Άνοιγμα για διάβασμα από το αρχείο. | +|  **ios::in**   | Άνοιγμα για ανάγνωση από το αρχείο. | 
-|  **ios::out**  | Άνοιγμα για γράψιμο στο αρχείο. | +|  **ios::out**  | Άνοιγμα για εγγραφή στο αρχείο. | 
-|  **ios::binary**  | Άνοιγμα για διάβασμα ή γράψιμο σε δυαδικό αρχείο.  | +|  **ios::binary**  | Άνοιγμα για ανάγνωση ή εγγραφή σε δυαδική μορφή.  | 
-|  **ios::ate**  | Θέτει τη θέση γραψίματος στο τέλος του αρχείου. Εάν δεν προσδιοριστεί το συγκεκριμένο //flag// η θέση γραψίματος τίθεται στην αρχή +|  **ios::app**  | Η θέση εγγραφής τίθεται στο τέλος του αρχείου. Εάν επιχειρήσετε να μεταβάλλετε τη θέση εγγραφής μέσω της συνάρτησης [[cpp:stream_random_io#μεταβολή_της_θέσης_ανάγνωσης_ή_εγγραφής|seekp]] __αυτό δεν θα έχει αποτέλεσμα__. | 
-|  **ios::app**  | Η θέση γραψίματος τίθεται στο τέλος του αρχείουπροσθέτοντας πληροφορία (//append//) στο υφιστάμενο αρχείο. |+|  **ios::ate**  | Θέτει τη θέση εγγραφής στο τέλος του αρχείου. Εάν δεν προσδιοριστεί το συγκεκριμένο //flag// η θέση εγγραφής τίθεται στην αρχή. Μπορείτε να μεταβάλλετε τη θέση εγγραφής μέσω της συνάρτησης [[cpp:stream_random_io#μεταβολή_της_θέσης_ανάγνωσης_ή_εγγραφής|seekp]] |
 |  **ios::trunc**  | Εάν το αρχείο υπάρχει ήδη και έχει περιεχόμενο, το υφιστάμενο περιεχόμενο διαγράφεται. | |  **ios::trunc**  | Εάν το αρχείο υπάρχει ήδη και έχει περιεχόμενο, το υφιστάμενο περιεχόμενο διαγράφεται. |
  
Line 65: Line 55:
 |  **fstream**  |  **ios::in %%|%% ios::out**  | Η τιμή δεν ισχύει εάν αλλάξετε την παράμετρο //mode//. Μπορείτε να επαναορίσετε τις τιμές | |  **fstream**  |  **ios::in %%|%% ios::out**  | Η τιμή δεν ισχύει εάν αλλάξετε την παράμετρο //mode//. Μπορείτε να επαναορίσετε τις τιμές |
  
-Για να ελέγξετε εάν ένα αρχείο έχει ανοίξει σωστά για διάβασμα μπορείτε να χρησιμοποιήσετε τη μέθοδο //is_open()// ως εξής:+Παρατηρήστε ότι η μέθοδος //open// δεν έχει επιστρεφόμενη τιμή για να ελέγξουμε την αποτυχία, ούτε παράγει κάποιο //exception//Για να ελέγξετε εάν ένα αρχείο έχει ανοίξει σωστά για διάβασμα ή γράψιμο μπορείτε να χρησιμοποιήσετε τη μέθοδο //is_open()// ως εξής:
 <code cpp> <code cpp>
 ofstream lena("lena.png", ios::out | ios::trunc | ios::binary); ofstream lena("lena.png", ios::out | ios::trunc | ios::binary);
Line 72: Line 62:
  
 <WRAP center round tip 80%> <WRAP center round tip 80%>
-Παρατηρήστε ότι στο παραπάνω παράδειγμα χρησιμοιούμε τον κατασκευαστή της κλάσης //ofstream// αντί για τη μέθοδο //open//. Τα ορίσματα που λαμβάνει ο κατασκευαστής και η σειρά τους είναι ταυτόσημα με αυτά της μεθόδου //open//.+Παρατηρήστε ότι στο παραπάνω παράδειγμα χρησιμοποιούμε τον κατασκευαστή της κλάσης //ofstream// αντί για τη μέθοδο //open//. Τα ορίσματα που λαμβάνει ο κατασκευαστής και η σειρά τους είναι ταυτόσημα με αυτά της μεθόδου //open//.
 </WRAP> </WRAP>
  
Line 84: Line 74:
 ===== Αρχεία κειμένου ===== ===== Αρχεία κειμένου =====
  
-//Streams// κειμένου είναι εκείνα τα streams που κατά το άνοιγμα του αρχείου δεν έχουν ορισμένο το //flag **ios::binary**//. Τα αρχεία αυτά υποθέτουμε ότι περιέχουν κείμενο και κατ' επέκταση μπορούμε να τα διαβάσουμε υποθέτοντας ότι οι λέξεις χωρίζονται μεταξύ τους από κενό χαρακτήρα ή χαρακτήρα αλλαγής γραμμής (''' ','\t','\n','\x0B','\f','\r''') και οι γραμμές χωρίζονται με χαρακτήρα αλλαγής γραμμής ('''\r','\n''').+//Streams// κειμένου είναι εκείνα τα streams που κατά το άνοιγμα του αρχείου δεν έχουν ορισμένο το //flag **ios::binary**//. Τα αρχεία αυτά υποθέτουμε ότι περιέχουν μόνο εκτυπώσιμους χαρακτήρες (δηλ. κείμενοκαι κατ' επέκταση μπορούμε να τα διαβάσουμε υποθέτοντας ότι οι λέξεις χωρίζονται μεταξύ τους από κενό χαρακτήρα ή χαρακτήρα αλλαγής γραμμής (''' ','\t','\n','\x0B','\f','\r''') και οι γραμμές χωρίζονται με χαρακτήρα αλλαγής γραμμής ('''\r','\n''').
  
 Ο τρόπος με τον οποίο γράφετε ή διαβάζετε είναι ο τρόπος που το κάνετε για τη βασική είσοδο και έξοδο. Ο τρόπος με τον οποίο γράφετε ή διαβάζετε είναι ο τρόπος που το κάνετε για τη βασική είσοδο και έξοδο.
-^  Γράψιμο σε αρχείο κειμένου  ^  Διάβασμα από αρχείο κειμένου  ^+^  Γράψιμο σε αρχείο κειμένου  ^  
 |<code cpp file_write.cpp> |<code cpp file_write.cpp>
 #include <iostream> #include <iostream>
Line 107: Line 97:
   myfile.close();   myfile.close();
 } }
-</code>|<code cpp file_read.cpp>+</code>
 + 
 +^ Διάβασμα από αρχείο κειμένου γραμμή-γραμμή ^ Διάβασμα από αρχείο κειμένου λέξη-λέξη και εκτύπωση κάθε λέξης σε νέα γραμμή ^ 
 +|<code cpp file_read_line_by_line.cpp>
 #include <iostream> #include <iostream>
 #include <fstream> #include <fstream>
Line 113: Line 106:
 using namespace std; using namespace std;
  
-#define MAX_LINE_LEN 128+#define MAX_LINE_LEN 1024 // really big!
  
 int main () { int main () {
Line 130: Line 123:
   myfile.close();     myfile.close();  
 } }
-</code>| +</code>|<code cpp file_read_word_by_word.cpp>
- +
-===== Έλεγχος της εσωτερικής κατάστασης του stream ===== +
- +
-Κάθε //stream// διαθέτει μία σειρά από //flags// που ενημερώνουν για την κατάσταση του. Τα //flags// αυτά αποθηκεύονται στην μεταβλητή //[[http://www.cplusplus.com/reference/ios/ios_base/iostate/|std::iosbase::iostate]]//. Συγκεκριμένα η μεταβλητή περιέχει τα παρακάτω //flags//+
- +
-^  flag  ^  Περιγραφή +
-|  **eofbit**  | End-Of-File reached while performing an extracting operation on an input stream. | +
-|  **failbit**  | The last input operation failed because of an error related to the internal logic of the operation itself. | +
-|  **badbit**  | Error due to the failure of an input/output operation on the stream buffer. | +
-|  **goodbit**  | No error. Represents the absence of all the above (the value zero). | +
- +
-Οι ακόλουθες μέθοδοι ενημερώνουν για την εσωτερική κατάσταση του //stream// επιστρέφοντας μία //boolean// τιμή ως εξής: +
-|  <code cpp>bool good() const;</code>  | Επιστρέφει //true// εάν κανένα από τα //error flags// (f**ailbit, badbit, eofbit**) δεν έχει τιμή //true//. | +
-|  <code cpp>bool bad() const;</code>  | Ελέγχει εάν το **badbit** είναι //true//. Το **badbit** λαμβάνει τη τιμή //true// εάν συμβεί κάποιο μη αναστρέψιμο σφάλμα στο εσωτερικό του //stream//. Εάν το **badbit** γίνει //true// οποιαδήποτε ενέργεια πάνω στο //stream// θα πρέπει να αποκλειστεί. | +
-|  <code cpp>bool eof() const;</code>  | Ελέγχει εάν το **eofdbit** είναι //true//. To **eofbit** γίνεται //true//, όταν η διαδικασία ανάγνωσης φτάνει στο τέλος του αρχείου. | +
-|  <code cpp>bool fail() const;</code>  | Ελέγχει εάν το **failbit** ή το **badbit** έχουν τιμή //true//. Το **failbit** λαμβάνει τη τιμή //true// εάν συμβεί κάποιο λάθος στη χρήση του //stream//. Το λάθος δεν θεωρείται μη αναστρέψιμο και το //stream// είναι πιθανό ότι μπορεί να χρησιμοποιηθεί για επιπλέον λειτουργίες εισόδου ή εξόδου. | +
- +
-===== Αλλαγή της θέσης ανάγνωσης ή εγγραφής στο stream ===== +
- +
-Τα //streams// εισόδου διατηρούν τη θέση ανάγνωσης και τα //strams// εξόδου τη θέση εγγραφής. //Streams// που υποστηρίζουν είσοδο και έξοδο διατηρούν ξεχωριστές θέσεις για ανάγνωση και για εγγραφή.  +
- +
-=== Ανάγνωση της θέσης ανάγνωσης ή εγγραφής === +
- +
-Η κλάση //istream// διαθέτει τη συνάρτηση //tellg// για την ανάγνωση της θέσης ανάγνωσης μέσα στο //stream//. Η συνάρτηση επιστρέφει ένα αντικείμενο του τύπου //streampos// και ορίζεται ως εξής: +
-<code cpp>streampos tellg();</code> +
- +
-Η κλάση //ostream// διαθέτει τη συνάρτηση //tellp// για την ανάγνωση της θέσης εγγραφής μέσα στο //stream//. Η συνάρτηση επιστρέφει ένα αντικείμενο του τύπου //streampos// και ορίζεται ως εξής: +
-<code cpp>streampos tellp();</code> +
- +
-=== Αλλαγή της θέσης ανάγνωσης ή εγγραφής === +
- +
-Η κλάση //istream// διαθέτει τη συνάρτηση //seekg// για την αλλαγή της θέσης ανάγνωσης μέσα στο //stream//. Η συνάρτηση επιστρέφει μία αναφορά στο υφιστάμενο //stream// και ορίζεται ως εξής: +
-<code cpp>istream& seekg (streampos pos); +
-istream& seekg (streamoff off, ios_base::seekdir way);</code> +
- +
-Η κλάση //ostream// διαθέτει τη συνάρτηση //seekp// για την αλλαγή της θέσης εγγραφής μέσα στο //stream//. Η συνάρτηση επιστρέφει μία αναφορά στο υφιστάμενο //stream// και ορίζεται ως εξής: +
-<code cpp>ostream& seekp (streampos pos); +
-ostream& seekp (streamoff off, ios_base::seekdir way);</code> +
- +
-Οι παράμετροι που λαμβάνουν οι συναρτήσεις //seekg// και //seekp// είναι οι εξής: +
-  * **pos:** Απόλυτη θέση μέσα στο //stream// ξεκινώντας από την αρχή. +
-  * **off:** Σχετική θέση μέσα στο //stream//. Συνδέεται με την τιμή της μεταβλητής **way**. +
-  * **way:** Μπορεί να πάρει μία από τις παρακάτω τιμές +
- +
-|  **ios::beg**  | αρχή του //stream// | +
-|  **ios::cur**  | τρέχουσα θέση του //stream// | +
-|  **ios::end**  | τέλος του //stream// | +
- +
-Ακολουθούν δύο παραδείγματα αλλαγής της θέσης ανάγωσης και εγγραφής πάνω στο //file stream//.  +
- +
-<code cpp fileseek.cpp> +
-#include <iostream> +
-#include <fstream> +
-using namespace std; +
-  +
-int main (int argc, char *argv[]) {   +
-  string filename; +
-  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;     +
-  } +
-  outfile << "I hate pointers   in C"; +
-  outfile.flush(); +
-   +
-  ifstream infile(filename.c_str()); +
-  if (!infile.is_open()) { +
-    cout << "[Read] Unable to open " << filename; +
-    return -1;     +
-  } +
-  string line; +
-  getline( infile, line ); +
-  cout << line << endl;   +
-     +
-  outfile.seekp(2); +
-  outfile << "love"; +
-  outfile.seekp(1, ios::cur); +
-  outfile << "references"; +
-  outfile.seekp(0,ios::end); +
-  outfile << "++" << endl; +
-   +
-  infile.seekg(0, ios::beg); +
-  getline( infile, line ); +
-  cout << line << endl;   +
-}</code> +
- +
-<code cpp filesize.cpp>+
 #include <iostream> #include <iostream>
 #include <fstream> #include <fstream>
 +#include <string>
 using namespace std; using namespace std;
  
 int main () { int main () {
-  streampos begin,end; +  string filename, word
-  string filename; +  cout << "Enter input filename: ";
-  cout << "Enter filename: ";+
   cin >> filename;   cin >> filename;
-  ifstream file(filename.c_str()); +  ifstream myfile (filename.c_str()); 
-  if (!file.is_open()) { +   
-    cout << "Unable to open " << filename;+  if (!myfile.is_open()) { 
 +    cout << "Unable to open file " << filename;
     return -1;         return -1;    
   }   }
-  begin = file.tellg(); +  while ( !myfile.eof() )  { 
-  file.seekg (0, ios::end)+    myfile >> word
-  end = file.tellg();+    cout << word << endl;  
 +  }
   myfile.close();   myfile.close();
-  cout << "file size is: " << (end-begin) << " bytes.\n";+      
 } }
-</code>+</code>|
  
 ===== Δυαδικά αρχεία ===== ===== Δυαδικά αρχεία =====
Line 246: Line 152:
 Για δυαδικά αρχεία η ανάγνωση και η εγγραφή με χρήση των τελεστών %%<<%% (//extraction operator//) και %%>>%% (//insertion operator//) δεν είναι εφικτή. Για τον λόγο αυτό τα //file streams// περιέχουν δύο μεθόδους για διάβασμα και γράψιμο δυαδικής πληροφορίας. Για δυαδικά αρχεία η ανάγνωση και η εγγραφή με χρήση των τελεστών %%<<%% (//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**. |+|  <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//. | |  <code cpp>ostream& write (const char* s, streamsize n);</code>  | Γράψιμο //n// στοιχείων τύπου //char// από το //s// προς το //stream//. |
  
-Δείτε το παρακάτω παράδειγμα ανάγνωσης και εγγραφής από δυαδικό αρχείο. Το πρόγραμμα αντιγράφει το περιεχόμενο ενός αρχείου σε ένα άλλο.+Δείτε το παρακάτω παράδειγμα ανάγνωσης και εγγραφής από δυαδικό αρχείο. Το πρόγραμμα αντιγράφει το περιεχόμενο ενός υφιστάμενου αρχείου σε ένα άλλο σε τμήματα των SIZE bytes.
  
 <code cpp binary_copy.cpp> <code cpp binary_copy.cpp>
Line 257: Line 163:
 using namespace std; using namespace std;
  
-#define SIZE 1+#define SIZE 512
    
 int main (int argc, char *argv[]) {   int main (int argc, char *argv[]) {  
Line 280: Line 186:
   while(!infile.eof()) {   while(!infile.eof()) {
     infile.read(buf, SIZE);         infile.read(buf, SIZE);    
-    outfile.write(buf, SIZE);+    outfile.write(buf, infile.gcount());
   }   }
   infile.close();   infile.close();
Line 286: Line 192:
 } }
 </code> </code>
 +
  
cpp/file_io.txt · Last modified: 2020/05/17 18:17 (external edit)