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
cpp:file_io [2017/05/09 08:42]
gthanos [Αλλαγή της θέσης ανάγνωσης ή εγγραφής στο stream]
cpp:file_io [2020/05/17 19:17]
gthanos
Line 1: Line 1:
-====== Η έννοια του stream ====== 
- 
-Η C++ εισάγει την έννοια του //stream//, ως μία σειρά από χαρακτήρες οι οποίοι μπορούν: 
-  * να γραφούν σε ένα αρχείο ή σε μία σειριακή συσκευή με τη σειρά που αυτοί εγγράφονται στο //stream//. 
-  * να διαβαστούν από ένα αρχείο ή από μία σειριακή συσκευή με τη σειρά που είναι αποθηκευμένοι ή με τη σειρά που εισήχθησαν στη συσκευή. 
- 
-Βασικά χαρακτηριστικά των //streams// είναι τα εξής: 
-  - Ένα //stream// μεταφράζεται πάντα σε μία ακολουθία χαρακτήρων. Τα //streams// δίνουν ένα ενιαίο //interface// προς τα αντικείμενα για οποιοδήποτε μέσω αποθήκευσης. Εάν μία κλάση μπορεί να γράψει σε ένα //stream// τότε μπορεί να γράψει σε όλα τα πιθανά //streams//. 
-  - Τα //streams// δουλεύουν αυτόματα με τους βασικούς τύπους δεδομένων. Για τους αναφορικούς τύπους μπορείτε να υπερφορτώσετε τους τελεστές %%>>%% και %%<<%% για είσοδο από το //stream// και έξοδο προς το //stream// αντίστοιχα. Η χρήση των τελεστών %%>>%% και %%<<%% απλοποιεί εξαιρετικά τον τρόπο με τον οποίο αλληλεπιδρούν τα προγράμματα με τα //streams//. 
- 
 ====== Είσοδος και έξοδος αρχείων ====== ====== Είσοδος και έξοδος αρχείων ======
  
-Η C++ παρέχει τις παρακάτω κλάσεις για είσοδο και έξοδο από αρχεία.  +Η //standard// βιβλιοθήκη της 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 129: Line 122:
     cout << line << '\n';        cout << line << '\n';   
   myfile.close();     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>| </code>|
  
-===== Έλεγχος της εσωτερικής κατάστασης του stream =====+===== Δυαδικά αρχεία =====
  
-Κάθε //stream// διαθέτει μία σειρά από //flags// που ενημερώνουν για την κατάσταση του. Τα //flags// αυτά αποθηκεύονται στην μεταβλητή //[[http://www.cplusplus.com/reference/ios/ios_base/iostate/|std::iosbase::iostate]]//. Συγκεκριμένα η μεταβλητή περιέχει τα παρακάτω //flags//.+Για δυαδικά αρχεία η ανάγνωση και η εγγραφή με χρήση των τελεστών %%<<%% (//extraction operator//) και %%>>%% (//insertion operator//) δεν είναι εφικτή. Για τον λόγο αυτό τα //file streams// περιέχουν δύο μεθόδους για διάβασμα και γράψιμο δυαδικής πληροφορίας.
  
- flag  ^  Περιγραφή  ^ + <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]].  
-|  **eofbit**  | End-Of-File reached while performing an extracting operation on an input stream. +|  <code cpp>ostream& write (const chars, streamsize n);</code>  Γράψιμο //n// στοιχείων τύπου //char// από το //s// προς το //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// τιμή ως εξής: +Δείτε το παρακάτω παράδειγμα ανάγνωσης και εγγραφής από δυαδικό αρχείο. Το πρόγραμμα αντιγράφει το περιεχόμενο ενός υφιστάμενου αρχείου σε ένα άλλο σε τμήματα των SIZE bytes.
-|  <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 ===== +<code cpp binary_copy.cpp>
- +
-Τα //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 <iostream>
 #include <fstream> #include <fstream>
 +#include <cmath>
 using namespace std; using namespace std;
 +
 +#define SIZE 512
    
 int main (int argc, char *argv[]) {   int main (int argc, char *argv[]) {  
   string filename;   string filename;
-  cout << "Enter output filename: ";+  cout << "Enter input filename: ";
   cin >> 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());   ifstream infile(filename.c_str());
   if (!infile.is_open()) {   if (!infile.is_open()) {
Line 203: Line 174:
     return -1;         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); +  cout << "Enter output filename: ";
-  getline( infile, line ); +
-  cout << line << endl;   +
-}</code> +
- +
-<code cpp filesize.cpp> +
-#include <iostream> +
-#include <fstream> +
-using namespace std; +
- +
-int main () { +
-  streampos begin,end; +
-  string filename; +
-  cout << "Enter filename: ";+
   cin >> filename;   cin >> filename;
-  ifstream file(filename.c_str()); +  ofstream outfile(filename.c_str(), ios::trunc); 
-  if (!file.is_open()) { +  if (!outfile.is_open()) { 
-    cout << "Unable to open " << filename;+    cout << "[Write] Unable to open " << filename;
     return -1;         return -1;    
   }   }
-  begin = file.tellg(); +   
-  file.seekg (0ios::end); +  char buf[SIZE];   
-  end = file.tellg(); +  while(!infile.eof()) { 
-  myfile.close(); +    infile.read(bufSIZE);     
-  cout << "file size is: " << (end-begin<< " bytes.\n";+    outfile.write(buf, infile.gcount()); 
 +  
 +  infile.close(); 
 +  outfile.close();
 } }
 </code> </code>
  
- 
-  
  
cpp/file_io.txt · Last modified: 2020/05/17 18:17 (external edit)