Objjggect Oriented Programming using C++ · Streams $ Input Stream – supplies data from disk file...

Post on 11-Aug-2020

0 views 0 download

Transcript of Objjggect Oriented Programming using C++ · Streams $ Input Stream – supplies data from disk file...

Object Oriented Programming j g gusing C++

FILE HANDLINGFILE HANDLINGLECTURE‐23

1

1

FILE HANDLINGFILE HANDLING

2

Introduction

All programs we looked earlier: i d f h k b dinput data from the keyboard.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 deviceWe can use secondary storage device.Data is packaged up on the storage device as data structures called files.

3

Streams

• A flow of charactersA flow of characters

• Input stream– Flow into programFlow into program

• Can come from keyboard

• Can come from fileCan come from file

• Output stream– Flow out of programFlow out of program

• Can go to screen

• Can go to file• Can go to file

4

Streams Usageg

• We’ve used streams alreadyWe ve used streams already– cin

• Input from stream object connected toInput 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

6

StreamsInput Stream – supplies data from disk file to the program.

Output Stream – receives data to the disk file from the program

The I/O system of C++ contains:

disk file from the program.

The I/O system of C contains:ifstream – provides input operations on files

fstream – supports for simultaneous input and

ofstream – provides output operations on files

7

pp poutput operations on files

Stream Classes

8

The Data Hierarchy

• From smallest to largestBi (bi di i )– Bit (binary digit)• 1 or 0

• Everything in computer ultimately represented as bits• Everything in computer ultimately represented as bits

• Cumbersome for humans to use

• Character setCharacter 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 Your namee.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 recordRecord 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, accounts‐receivable, inventory…Payroll, accounts receivable, inventory…

10

General File I/O Stepsp

• Declare a file name variableDeclare a file name variable• Associate the file name variable with

the disk file name• Open the fileOpen the file• Use the file• Close the file

11

Files and Streams

• C++ views file as sequence of bytesE d i h d f fil k– Ends with end‐of‐file marker

0 31 2 4 5 8 9...... n-1

end-of-file marker6 7

• 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 file‐open mode

ofstream outClientFile( "filename", fileOpenMode );– To attach a file later

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

13

Creating a Sequential-Access File

• File‐open modesFile open modesMode Descriptionios::in Open a file for input. ios::out Open a file for output. ios::trunc Discard the file’s contents if it exists (this is

also the default action for ios::out) ios::app Write all output to the end of the file. ios::ate 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.

ios::binary

Open a file for binary (i.e., non-text) input or output.

– ofstream opened for output by default• ofstream outClientFile( "clients.dat", ios::out );• ofstream outClientFile( "clients.dat");

14

Creating a Sequential-Access File

• OperationsO l d d t !– Overloaded operator!• !outClientFile

R t (t ) if b dbit f ilbit t• Returns nonzero (true) if badbit or failbit set– Opened non‐existent file for reading, wrong permissions

– Writing to file (just like cout)Writing to file (just like cout)• outClientFile << myVariable

– Closing fileClosing file• outClientFile.close()• Automatically closed when destructor calledy

15

// Create a sequential file.

#i l d <i t >#include <iostream>

#include <fstream>

using namespace std;

int main() {

// ofstream constructor opens file // ofstream constructor opens file

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

// exit program if unable to create file// 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 end of file to end input \n? ";<< Enter end‐of‐file to end input.\n? ;

int account;

char name[ 30 ] ch=‘y’;char name[ 30 ], ch= y ;

double balance;

// read account, name and balance from cin, then place in file

while (ch == ‘y’) {while (ch == y ) {

cin >> account >> name >> balance;

outClientFile << account << ' ' << name << ' ' << balance

<< endl;<< endl;

cout << "? ";

cin>>ch;

} // end while

return 0; // ofstream destructor closes file

} // d i} // end main

17

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

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

• Reading filesReading files– ifstream inClientFile( "filename", ios::in );– Overloaded !

• !inClientFile tests if file was opened properly

19

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

• File position pointers– Index of next byte to read/write

– Functions to reposition pointer

• seekg (seek get for istream class)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)Direction (ios::beg default)

– ios::beg ‐ relative to beginning of stream

– ios::cur ‐ relative to current position

– ios::end ‐ relative to endios::end relative to end

20

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

• Examples– fileObject.seekg(0)

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

– fileObject.seekg(n)• Goes to nth byte from beginning

fil Obj t k ( i )– fileObject.seekg(n, 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• Goes to last byte

– seekp similar21

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

• To find pointer locationTo find pointer location– tellg and tellplocation = fileObject tellg()– location = fileObject.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 ( !i Cli tFil ) if ( !inClientFile )

{

cerr << "File could not be opened" << endl;

exit( 1 );

} // end if } //

int request;

int account;

char name[ 30 ];

d bl b l double balance;

// 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:case 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;break;

} // end switch

24

// read account name and balance from file// read account, name and balance from fileinClientFile >> account >> name >> balance;

// display file contents (until eof)while ( !inClientFile eof() ) {while ( !inClientFile.eof() ) {

// display recordif ( shouldDisplay( request, balance ) )

outputLine( account name balance );outputLine( account, name, balance );

// read account, name and balance from fileinClientFile >> account >> name >> balance;

} // end inner while} // end inner while

inClientFile.clear(); // reset eof for next input inClientFile.seekg( 0 ); // move to beginning of filerequest = getRequest(); // get additional request from userrequest = 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 data300 White 0.00 400 Jones 32.87

• Insert new data

300 Worthington 0.00

300 White 0.00 400 Jones 32.87Data gets overwritten

– Problem can be avoided, but awkward

300 Worthington 0.00ones 32.87

26

Random-Access Files

• Instant accessInstant access– Want to locate record quickly

• Airline reservations Banking system ATMsAirline reservations, Banking system, ATMs

– Sequential files must search through each one

• Random access files are solution• Random‐access files are solution– Instant access

I d i h d i h d– Insert record without destroying other data

– Update/delete items without changing other data

27

Random-Access Files

• C++ imposes no structure on filesP d fil– Programmer must create random‐access files

– Simplest way: fixed‐length recordsl l i i i fil f d i d k• Calculate position in file from record size and key

0 200 300 400 500

byte offsets}100

}

} } } } } }

100bytes

100bytes

100bytes

100bytes

100bytes

100bytes

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()<< operator and write()

– outFile << number• Outputs number (int) as a char *• Variable number of bytes

– outFile.write( const char *, size );• Outputs raw bytesp y

• Takes pointer to memory location, number of bytes to write– Copies data directly from memory into file– Does not convert to char *Does not convert to char *

29

Creating a Random-Access File

• ExampleoutFile.write( reinterpret cast<const char *>(&number), ( p _ ( ),

sizeof( number ) );– &number is an int *

C t t t h * ith• Convert to const char * with reinterpret_cast

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

– read function similar (more later)read function similar (more later)

– Must use write/read when using raw, unformatted dataunformatted data• Use ios::binary for raw writes/reads

30

Creating a Random-Access File• Usually write entire struct or object to file

P bl t t t• Problem statement– Credit processing program

– Store at most 100 fixed‐length records

– Record• Account number (key)

• First and last name

• Balance• Balance

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

• Next: program to create blank 100‐record file 31

//clientData.h// Class ClientData definition used in Fig. 14.12–Fig. 14.15.#include <string>#include <string>#include <iostream>using namespace std;

class ClientData {class ClientData {public:// default ClientData constructorClientData( int = 0, string = "", string = "", double = 0.0 );

// accessor functions for accountNumbervoid setAccountNumber( int );int getAccountNumber() const;

// accessor functions for lastNamevoid setLastName( string );string getLastName() const;

32

// accessor functions for firstName

void setFirstName( string );

string getFirstName() const;string getFirstName() const;

// accessor functions for balance

void setBalance( double );( )

double getBalance() const;

private:

int accountNumber;

char lastName[ 15 ];

char firstName[ 10 ];

double balance;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() {ofstream outCredit( "credit.dat", ios::binary );( , y );

// exit program if ofstream could not open fileif ( !outCredit ) {

cout << "File could not be opened." << endl;pexit( 1 );

} // end if

34

// create ClientData with no information

ClientData blankClient;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} // end main

35

Writing Data Randomly to a Random-Access FilFile

• Use seekp to write to exact location in fileUse seekp to write to exact location in file– Where does the first record begin?

• Byte 0Byte 0

– The second record?• Byte 0 + sizeof(object)Byte 0 + sizeof(object)

– Any record?• (recordNum ‐ 1) * sizeof(object)(recordNum 1) sizeof(object)

36

int main() {

int accountNumber;

char lastName[ 15 ];

char firstName[ 10 ];

double balance;

ofstream outCredit( "credit.dat", ios::binary );ofstream outCredit( credit.dat , ios::binary );

// exit program if ofstream cannot open file

if ( !outCredit ) {

cout << "File could not be opened " << endl;cout << File could not be 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() <= 100 ) {g () ) {

// 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 user‐specified record

outCredit.seekp( ( client.getAccountNumber() ‐ 1 ) * sizeof( ClientData ) );

// write user‐specified information in file

outCredit write(reinterpret cast< const char * >( &client ) sizeof( ClientData ) );outCredit.write(reinterpret_cast< const char >( &client ), sizeof( ClientData ) );

38

// enable user to specify another account number

cout << "Enter account number\n? ";

cin >> accountNumber;cin >> accountNumber;

client.setAccountNumber( accountNumber );

} // end while}

return 0;

} // end main

39

Enter account number (1 to 100, 0 to end input)? 37Enter lastname, firstname, balance? Barker Doug 0.00Enter account number? 29? 29Enter lastname, firstname, balance? Stone Sam 34.98Enter account number Notice that accounts

can be created in any? 88Enter lastname, firstname, balance? Smith Dave 258.34

b

can be created in any order.

Enter account number? 33Enter lastname, firstname, balance? Dunn Stacey 314.33? Dunn Stacey 314.33Enter account number? 0

40

Reading Data Sequentially from a Random-A FilAccess 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 >> number with raw bytese u be y

• Upcoming program– Output data from a random‐access file

Go through each record sequentially– 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" << "Last Name“ << "First Name”<< "Balancecout << Account << Last Name << First Name << 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 recordif ( li A N b () ! 0 )if ( client.getAccountNumber() != 0 )

outputLine( cout, client );

// read next from file i C dit d( i t t t< h * >( & li t )inCredit.read( reinterpret_cast< char * >( &client ),

sizeof( ClientData ) ); } // end while

return 0;return 0;} // end main

// display single recordvoid outputLine( ostream &output const ClientData &record ) {void outputLine( ostream &output, const ClientData &record ) {

output << record.getAccountNumber()<< record.getLastName()<< record.getFirstName()<< record.getBalance() << endl;

} // end outputLine

43

Account Last Name First Name Balance33 3 3333 Dunn Stacey 314.3337 Barker Doug 0.0088 Smith Dave 258.3496 Stone Sam 34.98

44