File Processing
Contents
Random-Access Files
Creating a Random-Access File
Writing Data Randomly to a Random-Access File
Reading Data Sequentially from a Random-Access File
2
Random-Access Files
• 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
byte offsets
100 100 100 100 100 100
bytes bytes bytes bytes bytes bytes
Random-Access Files
➢ 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
1. #include <iostream>
2. #include <string>
3. #include <fstream>
4. using namespace std;
5. class ClientData {
6. public:
7. // Default ClientData constructor
8. ClientData(int = 0, string = "", string = "", double = 0.0);
9. // Accessor functions for accountNumber
10. void setAccountNumber(int);
11. int getAccountNumber() ;
12. // Accessor functions for lastName
13. void setLastName(string);
14. string getLastName() ;
15. // Accessor functions for firstName
16. void setFirstName(string);
17. string getFirstName() ;
18. // Accessor functions for balance
19. void setBalance(double);
20. double getBalance() ;
21. private:
22. int accountNumber;
23. char lastName[15];
24. char firstName[10];
25. double balance;
26. };
27. // Default constructor
28. ClientData::ClientData(int account, string first, string last, double balance) {
29. setAccountNumber(account);
30. setFirstName(first);
31. setLastName(last);
32. setBalance(balance);
33. }
34. // Set account number
35. void ClientData::setAccountNumber(int account) {
36. accountNumber = account;
37. }
38. // Get account number
39. int ClientData::getAccountNumber() {
40. return accountNumber;
41. }
42. // Set last name
43. void ClientData::setLastName(string last) {
44. // Ensure the last name does not exceed the array size
45. int length = ([Link]() < 15) ? [Link]() : 14;
46. for (int i = 0; i < length; ++i)
47. lastName[i] = last[i];
48. lastName[length] = '\0'; // Null-terminate the string
49. }
50. // Get last name
51. string ClientData::getLastName() {
52. return lastName;
53. }
54. // Set first name
55. void ClientData::setFirstName(string first) {
56. // Ensure the first name does not exceed the array size
57. int length = ([Link]() < 10) ? [Link]() : 9;
58. for (int i = 0; i < length; ++i)
59. firstName[i] = first[i];
60. firstName[length] = '\0'; // Null-terminate the string
61. }
62. // Get first name
63. string ClientData::getFirstName() {
64. return firstName;
65. }
66. // Set balance
67. void ClientData::setBalance(double balance) {
68. this->balance = balance;
69. }
70. // Get balance
71. double ClientData::getBalance() {
72. return balance;
73. }
74. int main() {
75. ofstream outCredit("[Link]", ios::binary);
76. if (!outCredit) {
77. cerr << "File could not be opened." << endl;
78. exit(1);
79. }
80. ClientData blankClient;
81. // Write 100 blank records to the file
82. for (int i = 0; i < 100; ++i)
83. [Link](reinterpret_cast<char*>(&blankClient), sizeof(ClientData));//explicit type conversion used to convert one
pointer type to another
84. cout << "File created and blank records written." << endl;
85. [Link]();
86. return 0;
87. }
Writing Data Randomly to a Random-Access File
• 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)
1. // Writing to a random-access file.
2. #include <iostream>
3. #include <fstream>
4. using namespace std;
5. int main() {
6. ofstream outCredit("[Link]", ios::in | ios::out | ios::binary);
7. // Exit if file cannot be opened
8. if (!outCredit) {
9. cerr << "File could not be opened." << endl;
10. exit(1);
11. }
12. ClientData client;
13. // Get user input
14. cout << "Enter account number (1 to 100, 0 to end input): ";
15. int accountNumber;
16. cin >> accountNumber;
17. while (accountNumber > 0 && accountNumber <= 100) {
18. // Get remaining account data
19. cout << "Enter last name, first name, balance: ";
20. string lastName, firstName;
21. double balance;
22. cin >> lastName >> firstName >> balance;
23. // Set client data
24. [Link](accountNumber);
25. [Link](lastName);
26. [Link](firstName);
27. [Link](balance);
28. // Seek position in file
29. [Link]((accountNumber - 1) * sizeof(ClientData));
30. // Write to file
31. [Link](reinterpret_cast<char*>(&client), sizeof(ClientData));
32. // Ask for next record
33. cout << "Enter account number (1 to 100, 0 to end input): ";
34. cin >> accountNumber;
35. }
36. return 0;
37. }
Reading Data Sequentially from a Random-Access File
1. // Reading from a random-access file.
2. #include <iostream>
3. #include <fstream>
4. #include <iomanip>
5. using namespace std;
6. int main() {
7. ifstream inCredit("[Link]", ios::binary);
8. if (!inCredit) {
9. cerr << "File could not be opened." << endl;
10. exit(1);
11. }
12. ClientData client;
13. cout << "Account Number" << setw(20) << "Name" << setw(10) << "Balance" << endl;
14. while ([Link](reinterpret_cast<char*>(&client), sizeof(ClientData))) {
15. cout << [Link]() << setw(20)
16. << [Link]() << ", " << [Link]()
17. << setw(10) << [Link]() << endl;
18. }
19. [Link]();
20. return 0;
21. }
// This program reads a random access file sequentially, updates
// data already written to the file, creates new data to be placed
// in the file, and deletes data previously in the file.
1. #include <iostream>
2. #include <fstream>
3. #include <iomanip> // For setw()
4. using namespace std;
5. int enterChoice();
6. void textFile(fstream&);
7. void updateRecord(fstream&);
8. void newRecord(fstream&);
9. void deleteRecord(fstream&);
10. int main() {
11. fstream creditFile("[Link]", ios::in | ios::out | ios::binary);
12. if (!creditFile) {
13. cerr << "File could not be opened." << endl;
14. exit(1);
15. }
16. int choice;
17. while ((choice = enterChoice()) != 5) {
18. switch (choice) {
19. case 1:
20. textFile(creditFile);
21. break;
22. case 2:
23. updateRecord(creditFile);
24. break;
25. case 3:
26. newRecord(creditFile);
27. break;
28. case 4:
29. deleteRecord(creditFile);
30. break;
31. default:
32. cout << "Incorrect choice." << endl; }
33. }
34. [Link]();
35. return 0;
36. }
37. int enterChoice() {
38. int menuChoice;
39. cout << "\nEnter choice:\n"
40. << "1 - Create a text file from the record file\n"
41. << "2 - Update an existing record\n"
42. << "3 - Add a new record\n"
43. << "4 - Delete an existing record\n"
44. << "5 - End program\n? ";
45. cin >> menuChoice;
46. return menuChoice;
47. }
48. void textFile(fstream& creditFile) {
49. [Link]();//Clears all error state flags on the stream. Without clear(), if a previous read or write set an error
flag, seekg() or seekp() might not work.
50. [Link](0, ios::beg);
51. ClientData client;
52. cout << "Account Number" << setw(20) << "Name" << setw(10) << "Balance" << endl;
53. while ([Link](reinterpret_cast<char*>(&client), sizeof(ClientData))) {
54. cout << [Link]() << setw(20)
55. << [Link]() << ", " << [Link]()
56. << setw(10) << [Link]() << endl; }
57. }
58. void updateRecord(fstream& creditFile) {
59. int accountNumber;
60. cout << "Enter account number to update (1 to 100): ";
61. cin >> accountNumber;
62. [Link]();
63. [Link]((accountNumber - 1) * sizeof(ClientData), ios::beg);
64. ClientData client;
65. [Link](reinterpret_cast<char*>(&client), sizeof(ClientData));
66. if ([Link]() == 0) {
67. cout << "Account #" << accountNumber << " has no information." << endl;
68. }
69. else {
70. cout << "Enter charge (+) or payment (-): ";
71. double transaction;
72. cin >> transaction;
73. [Link]([Link]() + transaction);
74. [Link]((accountNumber - 1) * sizeof(ClientData), ios::beg);
75. [Link](reinterpret_cast<const char*>(&client), sizeof(ClientData));
76. }
77. }
78. void newRecord(fstream& creditFile) {
79. int accountNumber;
80. cout << "Enter account number to create (1 to 100): ";
81. cin >> accountNumber;
82. [Link]();
83. [Link]((accountNumber - 1) * sizeof(ClientData), ios::beg);
84. ClientData client;
85. [Link](reinterpret_cast<char*>(&client), sizeof(ClientData));
86. if ([Link]() != 0) {
87. cout << "Account #" << accountNumber << " already contains information." << endl;
88. }
89. else {
90. cout << "Enter last name, first name, balance: ";
91. string lastName, firstName;
92. double balance;
93. cin >> lastName >> firstName >> balance;
94. [Link](accountNumber);
95. [Link](lastName);
96. [Link](firstName);
97. [Link](balance);
98. [Link]((accountNumber - 1) * sizeof(ClientData), ios::beg);
99. [Link](reinterpret_cast< char*>(&client), sizeof(ClientData)); }
100. }
101. void deleteRecord(fstream& creditFile) {
102. int accountNumber;
103. cout << "Enter account number to delete (1 to 100): ";
104. cin >> accountNumber;
105. [Link]();
106. [Link]((accountNumber - 1) * sizeof(ClientData), ios::beg);
107. ClientData client;
108. [Link](reinterpret_cast<char*>(&client), sizeof(ClientData));
109. if ([Link]() == 0) {
110. cout << "Account #" << accountNumber << " has no information." << endl;
111. }
112. else {
113. [Link](0);
114. [Link]("");
115. [Link]("");
116. [Link](0.0);
117. [Link]((accountNumber - 1) * sizeof(ClientData), ios::beg);
118. [Link](reinterpret_cast< char*>(&client), sizeof(ClientData));
119. }
120. }