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 [2018/05/21 02:38]
gthanos
cpp:file_io [2019/05/22 07:12]
gthanos [Άνοιγμα αρχείου για ανάγνωση και εγγραφή]
Line 1: Line 1:
 ====== Είσοδος και έξοδος αρχείων ====== ====== Είσοδος και έξοδος αρχείων ======
- 
-Η C++ εισάγει την έννοια του //stream//, ως μία σειρά από χαρακτήρες οι οποίοι μπορούν: 
-  * να εισαχθούν στο //stream// με συγκεκριμένη σειρά και να γραφούν σε ένα αρχείο ή σε μία σειριακή συσκευή με τη σειρά που εισήχθησαν. 
-  * να διαβαστούν από ένα αρχείο ή από μία σειριακή συσκευή με τη σειρά που είναι αποθηκευμένοι ή με τη σειρά που εισήχθησαν στη συσκευή. 
- 
-Βασικά χαρακτηριστικά των //streams// είναι τα εξής: 
-  - Ένα //stream// μεταφράζεται πάντα σε μία ακολουθία χαρακτήρων. Τα //streams// δίνουν ένα ενιαίο τρόπο γραφής και ανάγνωσης προς τα αντικείμενα που τα χρησιμοποιούν για οποιοδήποτε μέσο επικοινωνίας/αποθήκευσης. Εάν μία κλάση μπορεί να γράψει σε ένα //stream// τότε μπορεί να γράψει σε όλα τα πιθανά //streams//. 
-  - Τα //streams// δουλεύουν αυτόματα με τους βασικούς τύπους δεδομένων. Για τους αναφορικούς τύπους μπορείτε να υπερφορτώσετε τους τελεστές %%>>%% και %%<<%% για είσοδο από το //stream// και έξοδο προς το //stream// αντίστοιχα. Η χρήση των τελεστών %%>>%% και %%<<%% απλοποιεί εξαιρετικά τον κώδικα για να γράψουμε σε ένα //stream// ή να διαβάσουμε από αυτό. 
  
 Η C++ παρέχει τις παρακάτω κλάσεις για είσοδο και έξοδο από αρχεία.  Η C++ παρέχει τις παρακάτω κλάσεις για είσοδο και έξοδο από αρχεία. 
   - **[[http://www.cplusplus.com/reference/fstream/ifstream/|ifstream]]:** Κλάση για διάβασμα από αρχείο.   - **[[http://www.cplusplus.com/reference/fstream/ifstream/|ifstream]]:** Κλάση για διάβασμα από αρχείο.
   - **[[http://www.cplusplus.com/reference/fstream/ofstream/|ofstream]]:** Κλάση για γράψιμο σε αρχείο.   - **[[http://www.cplusplus.com/reference/fstream/ofstream/|ofstream]]:** Κλάση για γράψιμο σε αρχείο.
-  - **http://www.cplusplus.com/reference/fstream/fstream/|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.
Line 29: Line 21:
 </code> </code>
  
-===== Άνοιγμα αρχείου για διάβασμα και γράψιμο =====+===== Άνοιγμα αρχείου για ανάγνωση και εγγραφή =====
  
 Το άνοιγμα των αρχείων γίνεται μέσω της μεθόδου //open// η οποία προδιαγράφεται παρακάτω: Το άνοιγμα των αρχείων γίνεται μέσω της μεθόδου //open// η οποία προδιαγράφεται παρακάτω:
Line 39: 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 82: 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''').
  
 Ο τρόπος με τον οποίο γράφετε ή διαβάζετε είναι ο τρόπος που το κάνετε για τη βασική είσοδο και έξοδο. Ο τρόπος με τον οποίο γράφετε ή διαβάζετε είναι ο τρόπος που το κάνετε για τη βασική είσοδο και έξοδο.
Line 114: 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 136: Line 128:
 #include <string> #include <string>
 using namespace std; using namespace std;
- 
-#define MAX_LINE_LEN 128 
  
 int main () { int main () {
Line 144: Line 134:
   cin >> filename;   cin >> filename;
   ifstream myfile (filename.c_str());   ifstream myfile (filename.c_str());
-  char line[MAX_LINE_LEN];  
      
   if (!myfile.is_open()) {   if (!myfile.is_open()) {
Line 158: Line 147:
 } }
 </code>| </code>|
- 
-===== Έλεγχος της εσωτερικής κατάστασης του 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 <fstream> 
-using namespace std; 
- 
-int main () { 
-  streampos begin,end; 
-  string filename; 
-  cout << "Enter filename: "; 
-  cin >> filename; 
-  ifstream file(filename.c_str()); 
-  if (!file.is_open()) { 
-    cout << "Unable to open " << filename; 
-    return -1;     
-  } 
-  begin = file.tellg(); 
-  file.seekg (0, ios::end); 
-  end = file.tellg(); 
-  myfile.close(); 
-  cout << "file size is: " << (end-begin) << " bytes.\n"; 
-} 
-</code> 
  
 ===== Δυαδικά αρχεία ===== ===== Δυαδικά αρχεία =====
Line 273: 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//. |
  
-Δείτε το παρακάτω παράδειγμα ανάγνωσης και εγγραφής από δυαδικό αρχείο. Το πρόγραμμα αντιγράφει το περιεχόμενο ενός αρχείου σε ένα άλλο byte-byte.+Δείτε το παρακάτω παράδειγμα ανάγνωσης και εγγραφής από δυαδικό αρχείο. Το πρόγραμμα αντιγράφει το περιεχόμενο ενός υφιστάμενου αρχείου σε ένα άλλο σε τμήματα των SIZE bytes.
  
 <code cpp binary_copy.cpp> <code cpp binary_copy.cpp>
Line 284: 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 307: 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 313: Line 192:
 } }
 </code> </code>
 +
  
cpp/file_io.txt · Last modified: 2020/05/17 18:17 (external edit)