Chapter 13 – Advanced File Operations
;
Definition: A File is data stored on disk
;
There are 2 types of files:
;
;
How do our C++ programs interface with files?
;
Using file stream objects
;
example:
;
#include <fstream>
;
ifstream infile;
ofstream outfile;
;
int today=25;
string str;
;
infile.open(“myfile.txt”);
// can also be done in 1 stmt as: ifstream infile(“myfile.txt”);
;
if (infile.fail()) exit(1);
//OR
if (!infile) exit(); // if file does not exist, ifstream becomes NULL
;
// Use an ifstream object exactly as you use cin
infile >> str;
;
//WHEN YOU OPEN AN OFSTREAM, THE FILE POINTER IS AT THE BEGINNING OF THE FILE
//WHICH MEANS THAT IF THE FILE EXISTS, IT WILL BE ERASED
outfile.open(“myoutput.txt”);
if (outfile.fail())
{
cout << “error opening file”;
exit(1);
}
;
/**********USE OUTFILE**********/
// Write to a file exactly the way you use cout (except use a fstream object)
outfile << “today is Wednesday, March ” << today << endl;
;
// ALWAYS CLOSE FILES WHEN DONE (flushes buffer, maintains internal file status)
infile.close();
outfile.close();
;
// New type: fstream objects
;
fstream datafile;
;
datafile.open(“myfile.txt”, ios::in); // exactly the same thing as opening ifstream (infile)
;
if (datafile.fail()) exit(1);
;
char ch;
;
// read from datafile which contains characters
while (!datafile.eof())
{
datafile.get(ch);
cout << ch << “ “;
}
;
int num;
;
// another example: say our file contains numbers
while (datafile >> num) // if >> did not read, it will return NULL, this is an alternative for checking for eof()
{
cout << num << “ “;
}
;
//FLAGS: ios::in, ios::out, ios::app, ios::binary
//IF YOU OPEN AN FSTREAM OBJECT WITH ONLY ios::out YOUR FILE WILL BE DELETED
;
datafile.open(“myfile.txt”, ios::in | ios::out); // allows you to both read and write to a file
//OR
datafile.open(“myfile.txt”, ios::out | ios::app); // allows you to write to the end of a file
// same as ofstream that we defined above
;
// Say you want to check whether a file exists before opening it for output
fstream df;
;
df.open(“newoutput.txt”, ios::in);
if (!df.fail())
{
cout << “your output file already exists!”;
exit(1);
}
;
// now open for output if file does not exist
df.open(“newoutput.txt”, ios::out);
;
//.... check for fail, read, etc.
;
// PASS A FILE STREAM OBJECT BY REFERENCE
;
// example of a prototype:
;
bool func(fstream &datafile);
;
// getline with fstream objects
char cstr[10];
;
datafile.getline(cstr, 10);
;
// C++ strings and getline
string str;
getline(datafile, str); // 3rd optional parameter is any character as a delimiter
;
// BINARY FILES (Section 12.7)
;
The default mode for a file is text, i.e. each byte holds the ASCII code of a single character.
;
Numbers are converted to text:
;
ofstream myfile(“num.dat”);
short x = 1297;
myfile << x;
;
In memory, here is the representation of x:
;
|
00000101 |
00010001 |
;
On disk (i.e. in the file), here is x:
;
|
‘1’ |
‘2’ |
‘9’ |
‘7’ |
;
|
49 |
50 |
57 |
55 |
|
00110001 |
00110010 |
00111001 |
00110111 |
;
We may be interested in reading and writing directly in binary mode, without converting to and from char. In this way, we can write whole “chunks” of data, such as an entire object or even an entire array of objects.
;
First, you must open the file in binary mode:
;
fstream myfile;
myfile.open(“database.dat”, ios::out | ios::binary);
;
General form of writing:
;
fileObject.write(address, size);
address: beginning address in memory of the data to be written. Must be of type char*
size: number of bytes
;
Example1:
;
char letter = ‘A’;
myfile.write(&letter, sizeof(letter)); //sizeof returns the number of bytes that the object occupies
;
Example2: (an array can be written with one write statement)
;
char chararray[100];
;
myfile.write(chararray, sizeof(chararray));
;
// READ IN DATA from a binary file: same as write, just use function read
Example 1 cont.
myfile.read(&letter, sizeof(letter));
;
Example 2 cont.
char data[100];
myfile.read(data, sizeof(data));
;
What if my data is not of type char*?
;
CAST to char*
;
Example 3:
int x=5;
// I want to write x to a binary file
myfile.write(reinterpret_cast<char*>(&x), sizeof(x));
myfile.read(reinterpret_cast<char*>(&x), sizeof(x));
;
Example 4: writing/reading an array of integers
int numbers[100]={4,5,6,6,67,0};
;
myfile.write(reinterpret_cast<char*>numbers,sizeof(numbers));
myfile.read(reinterpret_cast<char*>numbers,sizeof(numbers));
;
Example 5: writing a structure object
struct gameItem {
char id[4];
double price;
int qty;
char name[25];
};
;
gameItem onegame;
//fill up the object with data
;
mydatabase.write(reinterpret_cast<char*>&onegame,sizeof(onegame);
;
Example 6: array of structures
gameItem db[1000];
mydatabase.write(reinterpret_cast<char*>db,sizeof(db);
;
/*********see program 12-15 in textbook**********/
;
RANDOM ACCESS FILES
;
Sequential access: start at the beginning and read byte 0,1,2,3,… in consecutive order.
Random access: I can jump my file pointer to any location in the file and read or write at that location. (similar functionality to accessing array elements.)
;
seekp (stands for seek put – use with ofstream and fstream objects)
seekg (stands for seek get – use for ifstream and fstream objects)
;
seekp(OFFSET as a long integer, flag of where to offset from);
example:
seekp(20L, ios::beg);
flags: ios::beg, ios::end, ios::cur
;
tellp: returns write position
tellg: returns read position
// REWIND to beginning
myfile.seekg(0L, ios::beg);
/******see programs 12-18, 12-20, 12-21, 12-22 ***********/
;
;