CPS120: Introduction to Computer Science Data Files
Working with Data Files It is possible to have a C++ program read and use a data file that is stored on your PC's hard drive Rarely does a program work without relatively large amounts of data. Rather than requiring the user to input large amounts of data, one often "reads" data from an external data file.
Using External Files External data files are simply text files (usually with the extension .txt or .dat) that are stored in the same folder as the C++ program which access them. It is possible to have a C++ program read files that are stored anywhere else on your PC's hard drive or network You will have to supply the path of those files in order to successfully access them.
Sequential Files Stores data as one long continuous piece of data To access a specific record (piece of data), though, the C++ program must read through all of the former pieces of data
Opening and Closing Data Files Files must be officially be opened before they are used by a C++ program
Required Compiler Directives Any program that uses file pointers must include the fstream.h header file with the compiler directive, #include <fstream.h> at the top of the program
Preparing to Use Files Opening a sequential-access file ofstream outfile; ofstream is a C++ keyword indicating the type of pointer that you created outfile is simply the programmer's chosen name for the file pointer (and can be any valid name) Open the file "mydata.txt" that is stored on your PC's hard drive outfile.open("mydata.txt", ios::out); or the shorter version outfile.open("mydata.txt"); output (out) is the default type of access for ofstream objects
Reading From a File Declare a file pointer as an ifstream object with: ifstream infile; ifstream is a keyword and infile is the name for the file pointer. Open the actual file for reading with: infile.open("mydata.txt", ios::in); or the shorter version infile.open("mydata.txt"); // numread.cpp // This program reads numbers from a data file until zero is encountered. // Then the program reports the sum and average of the numbers. #include<fstream.h> // necessary for file I/O #include<iostream.h> #include<iomanip.h> int main() { float x, sum; int count; ifstream infile; // declares file pointer named infile infile.open("floats.dat",ios::in); // open file for input sum = 0.0; // initialize sum count = 0; // initialize count if (infile) // If no error occurred while opening file { // input the data from the file. cout << "The numbers in the data file are as follows:\n" << setprecision(1); // set display to one decimal point cout.setf(ios::fixed); // prevent numbers from appearing in E-notation do // read numbers until 0.0 is encountered infile >> x; // get number from file cout << x << endl; // print number to screen sum = sum + x; // add number to sum count++; // increment count of how many numbers read } while(x != 0.0); // Output sum and average. cout << "The sum of the numbers is " << sum << endl; cout << "The average of the numbers (excluding zero) is " << sum / (count - 1) << endl; } else // If error occurred, display message. cout << "An error occurred while opening the file.\n"; infile.close(); // close the output file int getint; cin >> getint; return 0;
Using Sequential Files A sequential access file cannot be opened for input and output at the same time You can close a file that was opened for input and reopen it for output during a program's execution
Closing Files infile.close(); It is very important to always officially close a file, when you are finished using it from within a C++ program. The following statement would close the file, which is pointed to by the file pointer infile infile.close();
Preparing to Write Output It is wise to check to make sure that there wasn't an error actually opening the data file One can use an if statement like the following to protect the program from crashing. if (outfile) // same as if (outfile != 0) { outfile << "John Doe" << endl; } else { cout << "An error occurred while opening the file.\n"; } // loopwrite.cpp //This program stores numbers entered by the user until a zero is entered #include <iostream.h> #include <fstream.h> int main() { float x; // variable for user input ofstream outfile; // declares file pointer named outfile outfile.open("floats.dat", ios::out); // open the file floats.dat for output if (outfile) cout << "Enter a series of floating-point numbers "<< endl; cout << "separated by a space or a tab. "<< endl; cout << "Enter a zero at the end of the series \n"; do //repeat the loop until user enters zero cin >> x; // get number from the user outfile << x << endl; // write the number to the file } while ( x!= 0.0); } else cout << "Error opening file. |n"; outfile.close(); // close the output file return 0;
Writing Output To write data to a sequential-access data file you would use a statement like: outfile << "John Doe" << endl; to print that name to the next line in the data file pointed to by the file pointer, outfile. Open filewrit.cpp #include<iostream.h> #include<fstream.h> // necessary for file i/O int main() { char user_name[25]; int age; ofstream outfile; // declares file pointer named outfile cout << "Enter your name: "; // get name from user cin.get(user_name, 25); cout << "Enter your age: "; // get age from user cin >> age; outfile.open("NAME_AGE.DAT", ios::out); // open file for output if (outfile) // if no error occurs while opening file { // write the data to the file outfile << user_name << endl; // write the name to the file outfile << age << endl; // write the age to the file } else // If error occurred, display message. cout << "An error occurred while opening the file.\n"; return 0;
Reading Data From Files Use the insertion operator (>>). But, instead of using the cin keyword, you use the file pointer name that you declared. infile >> x; This statement stores the next numeric value in the file pointed to by the file pointer, infile, into the variable, x. // strread.cpp // This program reads bot the name and age from the file as strings and converts age // to an integer #include<fstream.h> // necessary for file I/O #include<iostream.h> #include<stdlib.h> // necessary for atoi function int main() { char user_name[25]; char user_age[4]; int age; ifstream infile; // declares file pointer named infile infile.open("NAME_AGE.DAT",ios::in); // open file for input if (infile) // If no error occurred while opening file { // input the data from the file. infile.get(user_name,25); // read the name from the file infile.ignore(80,'\n'); infile.get(user_age,4); // read the age from the file as a string age = atoi(user_age); cout << "The name read from the file is " << user_name << ".\n"; cout << "The age read from the file is " << age << ".\n"; } else // If error occurred, display message. cout << "An error occurred while opening the file.\n"; infile.close(); // close the input file return 0;
Appending Data Adding data to the end of a sequential-access data file is called appending Open the file using the ios::app stream operation mode as in: outfile.open("myfile.txt", ios::app); where the app is short for append. If you accidentally open the file with the ios::out mode, you will end up overwriting data in the file because C++ will write the first piece of outputted data at the beginning of the sequential-access data file // fileapp.cpp // this program adds data to the end of the data file, // rather than replacing whatever data was in the file. #include<iostream.h> #include<fstream.h> // necessary for file i/O int main() { char user_name[25]; int age; ofstream outfile; // declares file pointer named outfile cout << "Enter your name: "; // get name from user cin.get(user_name, 25); cout << "Enter your age: "; // get age from user cin >> age; outfile.open("NAME_AGE.DAT", ios::app); // open file for appending if (outfile) // if no error occurs while opening file { // write the data to the file outfile << user_name << endl; // write the name to the file outfile << age << endl; // write the age to the file } else // If error occurred, display message. cout << "An error occurred while opening the file.\n"; return 0;
Detecting the End of a File. Use the eof function to determine whether the end of a sequential-access file has been reached. This function returns a 1 (true) if an attempt has been made to read past the end of the file. do { infile >> x; if ( !infile.eof( ) ) cout << x << endl; } } while ( !infile.eof( ) ); // readEOF.cpp // This program continues to read floating point numbers from a file until the // EOF is reached #include<fstream.h> // necessary for file I/O #include<iostream.h> #include<iomanip.h> // necessary for setprecision manipulator int main() { float x; // Declare variable used for input. ifstream infile; // Declare file pointer named infile. infile.open("PRICES.DAT",ios::in); // Open file for input. if (infile) // If no error occurred while opening file, { // input the data from the file. cout << "The prices in the file are: \n" << setprecision(2); do // Loop while not the end of the file. infile >> x; // Get number from file. if (!infile.eof()) { // If not the end of file, cout << x << endl; // print the number to the screen. } } while (!infile.eof()); else // If error occurred, display message. cout << "An error occurred while opening the file.\n"; infile.close(); // Close the input file. return 0;
Using Multiple Data Files For one C++ program to access multiple data files, you simply have to create multiple file pointers (each one pointing to a different data file). For example, infile.open("inputfile.txt"); outfile.open("outputfile.txt");