Starting Out with C++ 1 Chapter 12: File Operations What is a File? A file is a collection on information, usually stored on some electronic medium. Information can be saved to files and then later reused.
Starting Out with C++ 2 File Names All files are assigned a name that is used for identification purposes by the operating system and the user. Extensions.bat Dos batch file.doc Word file.cpp C++ source file.h C++ header file.obj Object file.exe Executable file.html (.htm) Hypertext Markup Language file.java Java source file.txt Text file
Starting Out with C++ 3 The Process of Using a File Using a file in a program is a simple four- step process: –Declare the file. –Open the file. If the file does not yet exist and it is opened for reading, this is an error. If the file does not yet exist and it is opened for writing, the file is created. If the file does exists and it is opened for writing, the existing file is deleted (and will be written over). –Read/write to/from the file. –Close the file.
Starting Out with C++ 4 Different File Types File TypeDescription ofstream This data type can be used to create files and write information to them ifstream This data type can be used to create files and read information from them. fstream This data type can be used to create files, write information to them, and read information from them.
Starting Out with C++ 5 Opening a File You can declare a file in a separate statement and then open it. For example: ifstream in; ofstream out; fstream inout; in.open("customer.in"); out.open("customer.out"); inout.open("customer.inout");
Starting Out with C++ 6 Opening a File at Declaration A file may be opened at the same time it is declared. For example: –ifstream in ("names.in"); –ofstream out ("names.out"); –fstream inout ("names.inout", ios::in | ios::out);
Starting Out with C++ 7 File Mode Flags Mode FlagMeaning ios::app Append mode. If the file already exists, its contents are preserved and all output is written to the end of the file. ios::ate If the file already exists, the program goes directly to the end of it. ios::binary Binary mode. Information is written to or read from the file in pure binary format. ios::in Input mode. Information is read from the file. ios::nocreate If the file does not already exist, the open function call fails. ios::noreplace If the file exists, the open function call fails. ios::out Output mode. Information is written to the file. ios::trunc If the file exists, its contents are deleted.
Starting Out with C++ 8 What are ios:in and ios::out? They are actually constants that are thought of in binary. If you want to see what values they have, you can just print them. They are integers.
Starting Out with C++ 9 They are each powers of two, so in binary there is just one bit that is a one. The | is a binary “or”. Which means, the result is set if one or the other of the inputs is set. For example: 0101 OR 0011 = 0111 Thus, when we “or” the flags together, we produce a single binary number to pass as a parameter to the open method. Each bit that is set gives the method additional information (I want it opened as output and as input).
Starting Out with C++ 10 Testing for Open Errors To see if the file is opened correctly in.open("cust.dat"); if ( in==NULL ) { cout << "Error opening file named in.\n"; exit(1); } // if Or as if ( in.fail() ) or assert(in!=NULL) // remember #include
Starting Out with C++ 11 Closing a File System closes all files when a program finishes execution. Note: Despite the above statement, a file should be closed when a program is finished using it. Space is released at that time. Examples: – in.close(); – out.close();
Starting Out with C++ 12 Appending to a File – Program void main ( void ) {fstream dataFile; dataFile.open("demofile.txt", ios::out); dataFile << "Jones\n"; dataFile << "Smith\n"; dataFile.close(); dataFile.open("demofile.txt", ios::app); dataFile << "Willis\n"; dataFile << "Davis\n"; dataFile.close(); } // main
Starting Out with C++ 13 Detecting the End of a File The eof() member function reports when the end of a file has been encountered. In C++, “end of file” doesn’t mean the program is at the last piece of information in the file, but beyond it. The eof() function returns true when there is no more information to be read
Starting Out with C++ 14 End-of-File – Program void main ( void ) {fstream dataFile; char name[81]; dataFile.open( "demofile.txt", ios::in ); assert (dataFile ); dataFile >> name; while ( !dataFile.eof() ) { cout << name << endl; dataFile >> name; } // while dataFile.close(); cout << "\nDone.\n"; } // main
Starting Out with C++ 15 Passing File Stream Objects to Functions File stream objects may be passed by reference to functions – the file might not change, but the pointer to the next location in it does. bool openFileIn ( fstream &file, char name[] ) { bool status; file.open( name, ios::in ); return( !file.fail() ); } // openFileIn
Starting Out with C++ 16 State of Streams BitDescription ios::eofbit Set when the end of an input stream is encountered. ios::failbit Set when at attempted operation has failed. ios::hardfail Set when an unrecoverable error has occurred. ios::badbit Set when an invalid operation has been attempted ios::goodbit Set when all the flags above are not set. Indicates the stream is in good condition.
Starting Out with C++ 17 Member Functions for Streams FunctionDescription eof() Returns true if the eofbit flag is set, otherwise it returns false. fail() Returns true if the failbit or hardfail flags are set, otherwise returns false. bad() Returns true if the badbit flag is set, otherwise returns false. good() Returns true if the goodbit flag is set, otherwise returns false. clear() When called with no arguments, clears all the flags listed above. Can also be called with a specific flag as an argument.
Starting Out with C++ 18 Error Testing – Program void showState ( fstream &file ) {cout << "File Status:\n"; cout << " eof bit: " << file.eof() << endl; cout << " fail bit: " << file.fail() << endl; cout << " bad bit: " << file.bad() << endl; cout << " good bit: " << file.good() << endl; file.clear(); }// showState
Starting Out with C++ 19 ostream reference – cout or fout The advantage of ostream is that you can easily change from printing to the console to printing to a file. For example, void output(ostream & out){ out << "Animal " << getName() << " moves by " << getMove() << getBlood(); out << endl; } Now if I call output(cout), it prints to the screen, but if I call output(myFile), it prints to myFile. It is very convenient for debugging as you can see the file on the screen, but then easily switch to a regular file at a later time.
Starting Out with C++ 20 Member Functions for Reading and Writing Files File stream objects have member functions for more specialized file reading and writing. get – get a character from the input file. put – write a character to the output file.
Starting Out with C++ 21 Binary Files Binary files contain data that is unformatted for printing (stored in internal form), and not necessarily stored as ASCII text. A binary file is opened as file.open( "stuff.dat", ios::out | ios::binary );
Starting Out with C++ 22 Using a Binary File – Program void main ( void ) { ofstream file(“nums.dat", ios::binary ); int buffer[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cout << "Now writing the data to the file.\n"; file.write( reinterpret_cast buffer, sizeof(buffer) ); file.close(); file.open( "nums.dat", ios::in ); cout << "Now reading the data back into memory.\n"; file.read( reinterpret_cast buffer, sizeof(buffer) ); for ( int count = 0; count < 10; count++ ) cout << buffer[count] << " "; file.close(); } // main
Starting Out with C++ 23 Warning Don’t try to look at a binary file. It will look like garbage, as data is stored in internal form rather than as printable characters.
Starting Out with C++ 24 Creating Records with Structures Structures may be used to store fixed-length records to a file. struct Info { char name [LEN]; int age; char address1 [LEN]; char address2 [LEN]; char phone [LEN]; }; Since structures can contain a mixture of data types, you should always use the ios::binary mode when opening a file to store them.
Starting Out with C++ 25 Files and Structures – Program void main ( void ) {ofstream people( "people.dat", ios::binary); do{ // get info cin.getline(person.phone, 14); … people.write( reinterpret_cast &person, sizeof(person) ); } while ( toupper(again) == 'Y' ); people.close(); } // main reinterpret_cast just changes the following variable to an entry of type “type”. Other kinds of casts may also work.
Starting Out with C++ 26 Writing more than one file at a time If you declare an array of structs, you can write them all in one statement Example: Person people[5];… people.write( reinterpret_cast people, sizeof(people) ); since people is already a pointer, you don’t need to take an address Since sizeof(people) returns the size of the whole array, the whole array will be written.
Starting Out with C++ 27 Random Access Files Random Access means non-sequentially accessing information in a file. – Accessing by location, rather than linearly. Example, how you sort mail into bins.
Starting Out with C++ 28 Flags for Random Access Mode FlagsDescription ios::beg The offset is calculated from the beginning of the file. ios::end The offset is calculated from the end of the file. ios::cur The offset is calculated from the current position.
Starting Out with C++ 29 Random Access Member Functions seekg – used with files opened for input (the g stands for get). seekp – used with files opened for output (the p stands for put).
Starting Out with C++ 30 Examples Using seekp and seekg StatementHow it Affects the Position file.seekp(32L, ios::beg); Sets the write position to byte 32 from the beginning of the file. file.seekp(-10L, ios::end); Sets the write position to byte 10 from the end of the file. file.seekp(120L, ios::cur); Sets the write position to byte 120 from the current position. file.seekg(2L, ios::beg); Sets the read position to byte 2 from the beginning of the file. file.seekg(-100L, ios::end); Sets the read position to byte 100 from the end of the file. file.seekg(40L, ios::cur); Sets the read position to byte 40 from the current position. file.seekg(0L, ios::end); Sets the read position to the end of the file.
Starting Out with C++ 31 Using seekg – Program void main ( void ) {fstream file( "letters.txt", ios::in ); char ch; file.seekg( 5L, ios::beg ); file.get( ch ); cout << "Byte 5 from beginning: " << ch << endl; file.seekg( -10L, ios::end ); file.get(ch); cout << "Byte 10 from end: " << ch << endl; file.seekg( 3L, ios::cur ); file.get(ch); cout << "Byte 3 from current: " << ch << endl; file.close(); }// main
Starting Out with C++ 32 Other Member Functions tellp returns a long integer that is the current byte number of the file’s write position. tellg returns a long integer that is the current byte number of the file’s read position.
Starting Out with C++ 33 Opening a File for Both Input and Output You may perform input and output on an fstream file without closing it and reopening it.
Starting Out with C++ 34 Creating a Inventory File – Program struct Invtry {char desc[LEN]; int qty; float price; }; void main ( void ) {fstream inventory( "invtry.dat", ios::out | ios::binary ); Invtry record = { "", 0, 0.0 }; // Okay for char arrays, not for strings for ( int count = 0; count < 5; count++ ) {cout << "Now writing record " << count << endl; inventory.write( reinterpret_cast )&record, sizeof(record) ); } // for inventory.close(); } // main
Starting Out with C++ 35 Display Inventory File – Program (cont) inventory.read( reinterpret_cast &record, sizeof(record) ); while ( !inventory.eof() ) { cout << "Description: "; cout << record.desc << endl; cout << "Quantity: "; cout << record.qty << endl; cout << "Price: "; cout << record.price << endl << endl; inventory.read( reinterpret_cast &record, sizeof(record) ); } // while inventory.close(); } // main
Starting Out with C++ 36 Edit Inventory – Program void main ( void ) {fstream inventory( "invtry.dat", ios::in | ios::out | ios::binary ); f.seekg(0L,ios::end); // set position to end int numBytes = f.tellg(); // get the number of bytes int numRecord = numBytes/sizeof(CensusStat); cout << "My Records size is " <<numRecord<< endl; Invtry record;long recNum; cout << "Which record do you want to edit?"; cin >> recNum; inventory.seekg( recNum * sizeof(record), ios::beg ); inventory.read( reinterpret_cast &record, sizeof(record) ); // update information inventory.seekp( recNum * sizeof(record), ios::beg ); inventory.write( reinterpret_cast &record, sizeof(record) ); inventory.close(); } // main