Chapter 13 – Advanced File Operations

;

Definition: A File is data stored on disk

;

There are 2 types of files:

;

  1. Text files – ASCII   (e.g. Notepad document, any text file that's stored using vi or emacs, etc)
  2. Binary files  (executables, Word docs, anything that is not Plain Text)

;

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 ***********/

;

;