290 likes | 461 Vues
This guide covers file input/output operations in C++ using the fstream library. It explores the concepts of sequential and random access files, detailing how to work with both text and binary files. Learn about different access modes, methods for reading/writing data, and how to position file pointers for efficient data management. Examples demonstrate how to create, modify, and access files using both sequential and random access techniques. Ideal for programmers seeking a deeper understanding of file handling in C++.
E N D
fstream files • File: similar to vector of elements • Used for input and output • Elements of file can be • character (text) struct • object (non-text or binary) int • double array, ...
fstream methods • For files, cin.get( obj ); cout.put( obj ); • get() extracts one value from input buffer • put() inserts one value into output buffer
Sequential Access Files • File accessed in same order as written • Next input extraction picks up where last input extraction left off. • File is stream of elements • File may be of varying sizes • Limiting (think: cassette tape)
Random Access Files • Read and write fixed-length records that contain fields (like C++ structure or class) • Files can be accessed sequentially • Files can be accessed randomly (think: CDs) • File pointer must be positioned before input extraction operation for random access • Each record logically has relative record number (similar to index of arry, 0..n-1)
Sequential vs. Random Access • Random requires fixed-length records • Can contain characters, strings, ints, floats, struct or object instance • Can be written in • text format (character by character) • non-text (binary; written using same internal format as in memory)
Open Method filePtr.open (filename, access mode) ifstream ifs; ofstream ofs; • Open input file ifs.open (“names.txt”, ios::in); • Open output file ofs.open (“names.txt”, ios::out);
Open Access Modes Mode Description in Open for reading out Open for writing app Open for appending at end binary Opens in binary mode (non-text) to save space (no conversion)
Open Examples • Create file, write to it, and change some data ofs.open(“names.dat”, ios::in | ios::out); • Create file and make changes, all in non-text mode ofs.open(“names.dat”, ios::in | ios::out | ios::binary);
fstream Methods for Random Access • tellg() - returns (in bytes) location of file pointer in input file • tellp() - returns (in bytes) location of file pointer in output file • seekg() - repositions current file pointer in input file • seekp() - repositions current file pointer on output file • If both in and out, use tellg() and seekg()
seekg() Method • Moves the file pointer to a specific point in random-access data file • Format is: file.seekg(longNum, origin) • file - already initialized with open() • longNum - number of bytes to skip • origin - where to begin seeking • seekp() similar for output files
Values for origin C++ name Description ios::beg Beginning of file ios::cur Current file position ios::end End of file (all defined in fstream.h)
Examples of seekg() • Position file pointer at beginning of file ofs.seekg( 0L, ios::beg); 0L (zero L) is constant long integer zero • Moves file pointer zero bytes from beginning of the file
Example program using seekg() to read file twice void main() { char inChar; ifstream inFile; ofstream scrnl; inFile.open(“MYFILE.TXT”,ios::in); scrn.open(“CON”, ios::out); if (!inFile) { cout << “Error opening MYFILE.TXT”; exit(0);} while (inFile >> inChar) scrn << inChar; scrn.close(); inFile.clear(); // reset EOF1 inFile.seekg(0L, ios::begin); // to beginning while (inFile >> inChar) cout << inChar; inFile.close(); } See Fileio1.cpp
seekg() with file of structures or objects • Suppose have file of structures (inventory records) • Want 123rd occurrence of inventory record • Use sizeof() function filePtr.seekg( (123L * sizeof(struct inventory)), ios::beg);
Binary I/O • Requires primitive read and write methods • write (address, size) • read (address, size) • address - pointer to buffer of data (can be array of bytes or structure) • size - number of bytes to transfer; sizeof(datatype) function useful
Example of non-text modewith standard datatypes ofstream outFile; outFile.open(“myfile.dat”, ios::in|ios::out|ios::binary); int data = 30; int A[20]; outFile.write((char *) & data, sizeof(int)); outFile.write((char *) A, 20*sizeof(int)); outFile.seekg(0L, ios::beg); outFile.read((char *) A, 20*sizeof(int));
Example with objects - 1 #include <fstream.h> class person { public: void getData(void); void showData(void); protected: char name[40]; int age; };
Example with objects - 2 void person::getData(void) { cout << “Enter name: “; cin >> name; cout << “Enter age: “; cin >> age; } void person::showData(void) { cout << “Name: “ << name; cout << “Age: “ << age; }
Example with objects - 3 #include <iostream.h> void main(void) //create file of person objects { char ch; person pers; ofstream file; file.open (“PERSON.DAT”, ios::binary); do { cout << “Enter person’s data:”; pers.getData(); file.write((char*) &pers, sizeof(pers)); cout << “Enter another person(y/n)?”; cin >> ch; } while (ch == ‘y’); } Fileio3.ide
Example with objects - 4 #include <iostream.h> void main(void) //read file of person objects { char ch; person pers; ifstream file; file.open (“PERSON.DAT”, ios::binary); while (file.read((char *) &pers, sizeof(pers)) ) { cout << “Person”; pers.showData(); } } Fileio4.ide
Define a random accessnon-text stream class template <class T> class rstream { public: rstream (string& name); int get (unsigned int index, T & value); void put (unsigned int index, T & value); unsigned int length(); protected: fstream theStream; };
rstream constructor template <class T> rstream::rstream (string& name) { // construct an instance of rstream // convert string into C-style pointer variable char * cName = name.c_str(); // open the file for both input and output theStream.open (cName, ios::in | ios::out | ios::binary); }
put method for rstream template <class T> void rstream::put (unsigned int index, T & value) { // place a value into a random access stream // first position the stream theStream.seekg ( sizeof (T)* index ); // then write the value char & valuePtr = (char *) & value; theStream.write (valuePtr, sizeof(T)); }
get method for rstream template <class T> int rstream::get (unsigned int index, T & value) { // read a value from a random access stream // first position the stream theStream.seekg ( sizeof (T)* index ); // then read the value char & valuePtr = (char *) & value; theStream.read (valuePtr, sizeof(T)); // return the number of bytes read return theStream.gcount(); }
length method for rstream template <class T> unsigned int rstream::length ( ) { // return number of elements held in collection // first seek to end theStream.seekg ( 0L, ios::end ); // then divide current byte offset // by size of elements return theStream.tellg() / sizeof(T); }
References • Ford, William and William Topp. 1996. Data structures with C++. Englewood Cliffs: Prentice Hall. • Lafore, Robert. 1995. The Waite Group’s object-oriented programming in C++. Corte Madera, California: Waite Group Press. • Perry, Greg. 1992. C++ programming 101. Sams Publishing.