Fall 2013
Instructor: Reza Entezari-Maleki
Email: entezari@ce.sharif.edu
Sharif University of Technology
1
Fundamentals of Programming
Session 26
These slides have been created using Deitel’s slides
Fundamentals of Programming Session 26 Instructor: Reza - - PowerPoint PPT Presentation
Fundamentals of Programming Session 26 Instructor: Reza Entezari-Maleki Email: entezari@ce.sharif.edu 1 Fall 2013 These slides have been created using Deitels slides Sharif University of Technology Outlines Reading Data from a
Fall 2013
Sharif University of Technology
1
Session 26
These slides have been created using Deitel’s slides
Reading Data from a Sequential-Access File Updating Sequential-Access Files Random-Access Files Creating a Random-Access File Writing Data Randomly to a Random-Access File Reading Data Sequentially from a Random-Access
2
File position pointers
Number of next byte to read/write Functions to reposition pointer
seekg (seek get for istream class) seekp (seek put for ostream class)
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
3
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, 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
4
To find pointer location
tellg and tellp location = fileObject.tellg()
Upcoming example
Credit manager program List accounts with zero balance, credit, and debit
5
6
7
17 enum RequestType { ZERO_BALANCE = 1, CREDIT_BALANCE, 18 DEBIT_BALANCE, END }; 19 int getRequest(); 20 bool shouldDisplay( int, double ); 21 void outputLine( int, const char * const, double ); 22 int main() 23 { 24 // ifstream constructor opens the file 25 ifstream inClientFile( "clients.dat", ios::in ); 26 // exit program if ifstream could not open file 27 if ( !inClientFile ) { 28 cerr << "File could not be opened" << endl; 29 exit( 1 ); 30 } // end if 31 int request; 32 int account; 33 char name[ 30 ]; 34 double balance; 35 // get user's request (e.g., zero, credit or debit balance) 36 request = getRequest();
8
9
10
11
83 // determine whether to display given record 84 bool shouldDisplay( int type, double balance ) 85 { 86 // determine whether to display credit balances 87 if ( type == CREDIT_BALANCE && balance > 0 ) 88 return true; 89 // determine whether to display debit balances 90 if ( type == DEBIT_BALANCE && balance < 0 ) 91 return true; 92 // determine whether to display zero balances 93 if ( type == ZERO_BALANCE && balance == 0 ) 94 return true; 95 return false; 96 } // end function shouldDisplay 97 // display single record from file 98 void outputLine( int account, const char * const name, 99 double balance ) 100 { 101 cout << left << setw( 10 ) << account << setw( 13 ) << name 102 << setw( 7 ) << setprecision( 2 ) << right << balance 103 << endl; 104 } // end function outputLine
12
Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 1 Accounts with zero balances: 300 White 0.00 Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 3 Accounts with debit balances: 400 Stone -42.16
13
Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 2 Accounts with credit balances: 100 Jones 24.98 200 Doe 345.67 500 Rich 224.62 Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 4 End of run.
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
Formatted text different from internal representation Problem can be avoided, but awkward
14
300 White 0.00 400 Jones 32.87 300 Worthington 0.00ones 32.87 300 Worthington 0.00
Data gets overwritten
Instant access
Want to locate record quickly
Airline reservations, ATMs
Sequential files must search through each one
Random-access files are solution
Instant access Insert record without destroying other data Update/delete items without changing other data
15
C++ imposes no structure on files
Programmer must create random-access files Simplest way: fixed-length records
Calculate position in file from record size and key
16
200 300 400 500
byte offsets
100
100
bytes
100
bytes
100
bytes
100
bytes
100
bytes
100
bytes
"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 raw bytes Takes pointer to memory location, number of bytes to write
Copies data directly from memory into file
17
Example
sizeof( number ) );
&number is an int *
Convert to const char * with reinterpret_cast
sizeof(number)
Size of number (an int) in bytes
read function similar (more later) Must use write/read between compatible machines
Only when using raw, unformatted data
Use ios::binary for raw writes/reads
18
Usually write entire struct or object to file Problem statement
Credit processing program Store at most 100 fixed-length records Record
Account number (key) First and last name Balance
Account operations
Update, create new, delete, list all accounts in a file
Next: program to create blank 100-record file
19
20
1 #include <iostream> 2 #include <fstream> 3 #include <cstdlib> 4 #include <cstring> 5 using std::cerr; 6 using std::endl; 7 using std::ios; 8 using std::ofstream; 9 using std::string; 10 class ClientData { 11 public: 12 // default ClientData constructor 13 ClientData( int = 0, string = "", string = "", double = 0.0 ); 14 // accessor functions for accountNumber 15 void setAccountNumber( int ); 16 int getAccountNumber(); 17 // accessor functions for lastName 18 void setLastName(char *); 19 char * getLastName();
21
22
23
47 // set account-number value 48 void ClientData::setAccountNumber( int accountNumberValue ) 49 { 50 accountNumber = accountNumberValue; 51 } // end function setAccountNumber 52 // get last-name value 53 char * ClientData::getLastName() 54 { 55 return lastName; 56 } // end function getLastName 57 // set last-name value 58 59 void ClientData::setLastName(char * lastNameValue) 60 { 61 // copy at most 15 characters from string to lastName 62 int length = strlen( lastNameValue ); 63 length = ( length < 15 ? length : 14 ); 64 strncpy( lastName, lastNameValue, length ); 65 // append null character to lastName 66 lastName[ length ] = '\0';
24
67 } // end function setLastName 68 // get first-name value 69 char * ClientData::getFirstName() 70 { 71 return firstName; 72 } // end function getFirstName 73 // set first-name value 74 75 void ClientData::setFirstName(char * firstNameValue) 76 { 77 // copy at most 10 characters from string to firstName 78 int length = strlen( firstNameValue ); 79 length = ( length < 10 ? length : 9 ); 80 strncpy( firstName, firstNameValue, length ); 81 // append new-line character to firstName 82 firstName[ length ] = '\0'; 83 } // end function setFirstName
25
26
97 int main() 98 { 99 ofstream outCredit( "credit.dat", ios::binary ); 100 // exit program if ofstream could not open file 101 if ( !outCredit ) { 102 cerr << "File could not be opened." << endl; 103 exit( 1 ); 104 } // end if 105 // create ClientData with no information 106 ClientData blankClient; 107 108 // output 100 blank records to file 109 for ( int i = 0; i < 100; i++ ) 110
111 reinterpret_cast< const char * >( &blankClient ), 112 sizeof( ClientData ) ); 113 114 return 0; 115 116 } // end main
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)
27
28
29
13 int main() 14 { 15 int accountNumber; 16 char lastName[ 15 ]; 17 char firstName[ 10 ]; 18 double balance; 19 ofstream outCredit( "credit.dat", ios::binary ); 20 // exit program if ofstream cannot open file 21 if ( !outCredit ) { 22 cerr << "File could not be opened." << endl; 23 exit( 1 ); 24 } // end if 25 cout << "Enter account number " 26 << "(1 to 100, 0 to end input)\n? "; 27 // require user to specify account number 28 cin >> accountNumber; 29 ClientData client; 30 client.setAccountNumber( accountNumber );
30
31 // user enters information, which is copied into file 32 while ( client.getAccountNumber() > 0 && 33 client.getAccountNumber() <= 100 ) { 34 // user enters last name, first name and balance 35 cout << "Enter lastname, firstname, balance\n? "; 36 cin >> setw( 15 ) >> lastName; 37 cin >> setw( 10 ) >> firstName; 38 cin >> balance; 39 // set record lastName, firstName and balance values 40 client.setLastName( lastName ); 41 client.setFirstName( firstName ); 42 client.setBalance( balance ); 43 // seek position in file of user-specified record 44
45 sizeof( ClientData ) ); 46 // write user-specified information in file 47
48 reinterpret_cast< const char * >( &client ), 49 sizeof( ClientData ) );
31
32
Enter account number (1 to 100, 0 to end input) ? 37 Enter lastname, firstname, balance ? Barker Doug 0.00 Enter account number ? 29 Enter lastname, firstname, balance ? Brown Nancy -24.54 Enter account number ? 96 Enter lastname, firstname, balance ? Stone Sam 34.98 Enter account number ? 88 Enter lastname, firstname, balance ? Smith Dave 258.34 Enter account number ? 33 Enter lastname, firstname, balance ? Dunn Stacey 314.33 Enter account number ? 0
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 bytes
>> expects char *
Upcoming program
Output data from a random-access file Go through each record sequentially
If no data (accountNumber == 0) then skip
33
34
35
36
35 // read all records from file 36 while ( inCredit && !inCredit.eof() ) { 37 // display record 37 if ( client.getAccountNumber() != 0 ) 38
39 // read next from file 40 inCredit.read( reinterpret_cast< char * >( &client ), 41 sizeof( ClientData ) ); 42 } // end while 43 return 0; 44 } // end main 45 46 // display single record 47 void outputLine( ostream &output, const ClientData &record ) 48 { 49 output << left << setw( 10 ) << record.getAccountNumber() 50 << setw( 16 ) << record.getLastName().data() 51 << setw( 11 ) << record.getFirstName().data() 52 << setw( 10 ) << setprecision( 2 ) << right << fixed 53 << showpoint << record.getBalance() << endl; 54 } // end outputLine
37
Account Last Name First Name Balance 29 Brown Nancy -24.54 33 Dunn Stacey 314.33 37 Barker Doug 0.00 88 Smith Dave 258.34 96 Stone Sam 34.98