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 08:42]
gthanos [Αλλαγή της θέσης ανάγνωσης ή εγγραφής στο stream]
cpp:file_io [2019/05/21 06:53]
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 43: Line 33:
 |  **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)