You are on page 1of 44

Object j Oriented Programming g g using C++

FILE HANDLING
LECTURE23

FILE HANDLING

Introduction

All programs we looked earlier:


input data i d from f the h keyboard k b d. output data to the screen.

Output would be lost as soon as we exit from the program. How do we store data permanently?.
We can use secondary storage device. device Data is packaged up on the storage device as data structures called files.
3

Streams
A flow of characters Input stream
Flow into program

Can come from keyboard Can come from file Output stream
Flow out of program

Can go to screen Can go to file


4

Streams Usage g
We Weve ve used streams already
cin

Input from stream object connected to keyboard


cout

Output to stream object connected to screen Can define other streams


To or from files Used similarly as cin, cout
5

File input and output streams

Streams

Input Stream supplies data from disk file to the program. Output Stream receives data to the disk file from the program program. The I/O system of C C++ contains:
ifstream provides input operations on files ofstream provides output operations on files fstream supports pp for simultaneous input p and output operations on files
7

Stream Classes

The Data Hierarchy From smallest to largest


Bit Bi (bi (binary di digit) i)
1 or 0 Everything in computer ultimately represented as bits Cumbersome for humans to use Character set
Digits, letters, symbols used to represent data Every character represented by 1's and 0's

Byte: 8 bits
Can store a character (char)
9

The Data Hierarchy (contd.)


From smallest to largest (continued) Field: group of characters with some meaning

e.g., e g Your name


Record: group of related fields

struct or class in C++ In payroll system, could be name, S#, address, wage Each field associated with same employee Record key: field used to uniquely identify record

File: group of related records

Payroll for entire company Sequential file: records stored by key


Database: group of related files

Payroll, accountsreceivable, inventory


10

General File I/O Steps p


Declare a file name variable Associate the file name variable with the disk file name Open the file Use the file Close the file
11

Files and Streams


C++ views file as sequence of bytes
Ends E d with i h end dof ffile fil marker k
0 1 2 3 4 5 6 7 8 9 ... ... n-1 end-of-file marker

When file opened


Object created, stream associated with it cin, cout, etc. created when <iostream> included
Communication between program and file/device
12

Creating a Sequential-Access File


C++ imposes no structure on file Concept of "record" must be implemented by programmer To open file, create objects Creates "line of communication" from object to file Classes

ifstream (input only) ofstream (output only) fstream (I/O) (/ )


Constructors take file name and fileopen mode
ofstream outClientFile( "filename", fileOpenMode );

To attach a file later


ofstream outClientFile; outClientFile.open( "filename", fileOpenMode);

13

Creating a Sequential-Access File


Fileopen modes
Mode ios::in ios::out ios::trunc ios::app ios::ate Description Open a file for input. Open a file for output. Discard the files contents if it exists (this is also the default action for ios::out ) Write all output to the end of the file. Open a file for output and move to the end of the file (normally used to append data to a file). Data can be written anywhere in the file. Open a file for binary (i.e., non-text) input or output.

ios::binary

ofstream opened for output by default


ofstream outClientFile( "clients.dat", ios::out ); ofstream outClientFile( "clients.dat");
14

Creating a Sequential-Access File


Operations
Overloaded O l d d operator! t !
!outClientFile Returns R t nonzero (true) (t ) if badbit b dbit or failbit f ilbit set t
Opened nonexistent file for reading, wrong permissions

Writing to file (just like cout)


outClientFile << myVariable

Closing file
outClientFile.close() y closed when destructor called Automatically
15

// Create a sequential file. #i l d <iostream> #include <i t > #include <fstream> using namespace std; int main() { // ofstream constructor opens file ofstream outClientFile( "clients.dat", ios::out ); // exit program if unable to create file if ( !outClientFile ) { // overloaded ! operator cout << "File could not be opened" << endl; exit( ( 1 ); ) } // end if

16

cout << "Enter the account, name, and balance." << endl << "Enter Enter endoffile to end input.\n? input \n? "; ; int account; char name[ 30 ], ] ch= ch=y; y; double balance; // read account, name and balance from cin, then place in file while (ch == y) y){ cin >> account >> name >> balance; outClientFile << account << ' ' << name << ' ' << balance << endl; cout << "? "; cin>>ch; } // end while return 0; // ofstream destructor closes file } // end d main i
17

Enter the account, name, and balance. Enter N to end input. p ? Y 100 Jones 24 24.98 98 ? Y 200 Doe 345.67 ? Y 300 White 0.00 ? Y 400 Stone -42.16

18

Reading Data from a Sequential-Access Sequential Access File Reading files


ifstream inClientFile( "filename", ios::in );

Overloaded !
!inClientFile tests if file was opened properly

19

Reading Data from a Sequential-Access Sequential Access File


File position pointers Index of next byte to read/write Functions to reposition pointer

seekg (seek get for istream class) seekp (seek put for ostream class) Files have "get" and "put" pointers
seekg and seekp take offset and direction

Offset: number of bytes relative to direction Direction (ios::beg default)


ios::beg relative to beginning of stream ios::cur relative to current position ios::end relative to end
20

Reading Data from a Sequential-Access Sequential Access File


Examples fileObject.seekg(0)

Goes to front of file (location 0) because ios::beg is default


fileObject.seekg(n)

Goes to nth byte from beginning


fileObject.seekg(n, fil Obj t k ( i ios::cur) )

Goes n bytes forward


fileObject.seekg(y, ios::end)

Goes y bytes back from end


fileObject.seekg(0, ios::cur)

Goes to last byte


seekp similar
21

Reading Data from a Sequential-Access Sequential Access File To find pointer location
tellg and tellp location = fileObject fileObject.tellg() tellg()

Upcoming example
Credit manager program List accounts with zero balance, credit, and debit

22

int main() { // ifstream constructor opens the file ifstream inClientFile( "clients.dat", ios::in ); // exit program if ifstream could not open file if ( !inClientFile !i Cli tFil ) { cerr << "File could not be opened" << endl; exit( 1 ); } // end if int request; int account; char name[ 30 ]; d bl balance; double b l // get user's request (e.g., zero, credit or debit balance) request = getRequest();

23

// process user's request while ( request != END ) { switch ( request ) { case ZERO_BALANCE: ZERO BALANCE: cout << "\nAccounts with zero balances:\n"; break; case CREDIT_BALANCE: cout << "\nAccounts with credit balances:\n"; break; case DEBIT_BALANCE: cout << "\nAccounts with debit balances:\n"; break; } // end switch

24

// read account account, name and balance from file inClientFile >> account >> name >> balance; // display file contents (until eof) while ( !inClientFile !inClientFile.eof() eof() ) { // display record if ( shouldDisplay( request, balance ) ) outputLine( account, account name name, balance ); // read account, name and balance from file inClientFile >> account >> name >> balance; } // end inner while inClientFile.clear(); // reset eof for next input inClientFile.seekg( 0 ); // move to beginning of file request = getRequest(); // get additional request from user } // end outer while

25

Updating Sequential-Access Files


Updating sequential files
Risk overwriting other data Example: change name "White" to "Worthington"

Old data
300 White 0.00 400 Jones 32.87

Insert new data


300 Worthington 0.00 300 White 0.00 400 Jones 32.87

Data gets overwritten


300 Worthington 0.00ones 32.87

Problem can be avoided, but awkward

26

Random-Access Files
Instant access
Want to locate record quickly
Airline reservations reservations, Banking system system, ATMs

Sequential files must search through each one

Randomaccess files are solution


Instant access Insert I record d without ih d destroying i other h d data Update/delete items without changing other data
27

Random-Access Files
C++ imposes no structure on files
P Programmer must create random d access files fil Simplest way: fixedlength records
Calculate l l position ii i in fil file f from record d size i and dk key
0 100 200 300 400 500

} }
100

byte offsets

}
100

}
100

}
100

}
100

}
100

bytes

bytes

bytes

bytes

bytes

bytes

28

Creating a Random-Access File


"1234567" (char *) vs 1234567 (int) char * takes 8 bytes (1 for each character + null) int takes fixed number of bytes (perhaps 4)

123 same size in bytes as 1234567


<< operator and write() outFile << number

Outputs number (int) as a char * Variable number of bytes


outFile.write( const char *, size );

Outputs p raw bytes y Takes pointer to memory location, number of bytes to write
Copies data directly from memory into file Does not convert to char *
29

Creating a Random-Access File


Example
outFile.write( ( reinterpret p _cast<const char *>(&number), ( ), sizeof( number ) );

&number is an int *
C Convert tt to const t char h * with ith reinterpret_cast

sizeof(number)
Size of number (an int) in bytes

read function similar (more later) Must use write/read when using raw, unformatted data
Use ios::binary for raw writes/reads
30

Creating a Random-Access File


Usually write entire struct or object to file Problem P bl statement t t t
Credit processing program Store at most 100 fixedlength records Record
Account number (key) First and last name Balance

Account operations
Update, Update create new, new delete, delete list all accounts in a file

Next: program to create blank 100record file

31

//clientData.h // Class ClientData definition used in Fig. 14.12Fig. 14.15. #include <string> #include <iostream> using namespace std; class ClientData { public: // default ClientData constructor ClientData( int = 0, string = "", string = "", double = 0.0 ); // accessor functions for accountNumber void setAccountNumber( int ); int getAccountNumber() const; // accessor functions for lastName void setLastName( string ); string getLastName() const;

32

// accessor functions for firstName void setFirstName( string ); string getFirstName() const; // accessor functions for balance void setBalance( ( double ) ); double getBalance() const; private: int accountNumber; char lastName[ 15 ]; char firstName[ 10 ]; double balance; }; // end class ClientData

33

// clientData.cpp // Creating a randomly accessed file. #include <iostream> #include <fstream> using namespace std; #include "clientData.h" // ClientData class definition int main() { ( "credit.dat", , ios::binary y ); ofstream outCredit( // exit program if ofstream could not open file if ( !outCredit ) { p << endl; cout << "File could not be opened." exit( 1 ); } // end if

34

// create ClientData with no information ClientData blankClient; // output 100 blank records to file for ( int i = 0; i < 100; i++ ) outCredit.write( reinterpret_cast< const char * >( &blankClient ), sizeof( ClientData ) ); return 0; } // end main

35

Writing Data Randomly to a Random-Access File Fil Use seekp to write to exact location in file
Where does the first record begin?
Byte 0

The second record?


Byte 0 + sizeof(object)

Any record?
(recordNum 1) * sizeof(object)

36

int main() { int accountNumber; char lastName[ 15 ]; char firstName[ 10 ]; double balance; ofstream outCredit( "credit.dat", credit.dat , ios::binary ); // exit program if ofstream cannot open file if ( !outCredit ) { cout << "File File could not be opened opened." << endl; exit( 1 ); } // end if cout << "Enter account number << "(1 to 100, 0 to end input)\n? "; // require user to specify account number ClientData client; cin >> accountNumber; client.setAccountNumber( accountNumber );

37

// user enters information, which is copied into file while ( client.getAccountNumber() > 0 && client.getAccountNumber() g () <= 100 ) { // user enters last name, first name and balance cout << "Enter lastname, firstname, balance\n? "; cin >> lastName; cin >> firstName; cin >> balance; // set record lastName, firstName and balance values client.setLastName( lastName ); client.setFirstName( ( firstName ) ); client.setBalance( balance ); // seek position in file of userspecified record outCredit.seekp( ( client.getAccountNumber() 1 ) * sizeof( ClientData ) ); // write userspecified information in file outCredit write(reinterpret cast< const char * >( &client ) outCredit.write(reinterpret_cast< ), sizeof( ClientData ) );
38

// enable user to specify another account number cout << "Enter account number\n? "; cin >> accountNumber; client.setAccountNumber( accountNumber ); } // end while return 0; } // end main

39

Enter account number (1 to ? 37 Enter lastname, firstname, ? Barker Doug 0.00 Enter account number ? 29 Enter lastname, firstname, ? Stone Sam 34.98 Enter account number ? 88 Enter lastname, firstname, ? Smith Dave 258.34 Enter account number b ? 33 Enter lastname, firstname, ? Dunn Stacey 314.33 Enter account number ? 0

100, 0 to end input) balance

balance

balance

Notice that accounts can be created in any order.

balance

40

Reading Data Sequentially from a RandomA Access Fil File


read similar to write Reads raw bytes from file into memory
inFile.read( reinterpret_cast<char *>( &number ), sizeof( int ) );

&number: location to store data sizeof(int): how many bytes to read


Do not use inFile e >> number u be with raw bytes y

Upcoming program Output data from a randomaccess file Go through each record sequentially

If no data (accountNumber == 0) then skip

41

int main() { ifstream inCredit( "credit.dat", ios::in ); // exit program if ifstream cannot open file if ( !inCredit ) { cout << "File could not be opened." << endl; exit( 1 ); } // end if cout << "Account" Account << "Last Last Name Name << "First First Name<< Name << "Balance Balance << endl; ClientData client; // create record // read first record from file inCredit.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) );

42

// read all records from file while ( ! inCredit.eof() ) { // display record if ( client.getAccountNumber() li A N b () ! != 0 ) outputLine( cout, client ); // read next from file i C dit inCredit.read( d( reinterpret_cast< i t t t< char h * >( & &client li t ) ), sizeof( ClientData ) ); } // end while return 0; } // end main // display single record void outputLine( ostream &output &output, const ClientData &record ) output << record.getAccountNumber() << record.getLastName() << record.getFirstName() << record.getBalance() << endl; } // end outputLine {

43

Account 33 37 88 96

Last Name Dunn Barker Smith Stone

First Name Stacey Doug Dave Sam

Balance 3 314.33 33 0.00 258.34 34.98

44

You might also like