2. When the app executes, another compiler (known as the just-in-time compiler
17.7 Case Study: Credit Inquiry Program
MethodopenButton_Click
When the user clicksOpen File, the program calls event handleropenButton_Click(lines 21–64). Line 27 creates anOpenFileDialog, and line 29 calls itsShowDialogmethod to dis- play theOpendialog (see the second screenshot in Fig. 17.11). The behavior and GUI for theSaveandOpendialog types are identical, except thatSaveis replaced byOpen. If the user selects avalidfile name, lines 47–48 create aFileStreamobject and assign it to reference
input. We pass constantFileMode.Openas the second argument to theFileStreamcon- structor to indicate that theFileStreamshould open the file if it exists or throw aFileNot-
FoundExceptionif it does not. (In this example, theFileStreamconstructor willnotthrow aFileNotFoundException, because theOpenFileDialogis configured to check that the file exists.) In the last example (Fig. 17.9), we wrote text to the file using aFileStreamobject withwrite-only access. In this example (Fig. 17.11), we specifyread-only accessto the file by passing constantFileAccess.Readas the third argument to theFileStreamconstructor.
ThisFileStreamobject is used to create aStreamReaderobject in line 51. TheFileStream object specifies the file from which theStreamReaderobject will read text.
MethodnextButton_Click
When the user clicks the Next Record button, the program calls event handler
nextButton_Click(lines 67–105), which reads the next record from the user-specified file. (The user must clickNext Recordafter opening the file to view the first record.) Line 72 callsStreamReadermethodReadLineto read the next record. If an error occurs while reading the file, anIOExceptionis thrown (caught at line 100), and the user is notified (lines 102–103). Otherwise, line 75 determines whetherStreamReadermethodReadLine returnednull(i.e., there’s no more text in the file). If not, line 77 uses methodSplitof classstringto separate the stream of characters that was read from the file into tokens (strings) that represent theRecord’s properties—the second argument indicates that the tokens are delimited by commas in this file. These properties are then stored by construct- ing aRecordobject using the properties as arguments (lines 79–82). Line 85 displays the
Recordvalues in theTextBoxes. IfReadLinereturnsnull, the program closes theStream-
Readerobject (line 90), automatically closing the FileStreamobject, then notifies the user that there are no more records (lines 96–97).
17.7 Case Study: Credit Inquiry Program
To retrieve datasequentiallyfrom a file, programs normally start from thebeginningof the file, reading consecutively until the desired data is found. It sometimes is necessary to pro- cess a filesequentiallyseveral times (from thebeginningof the file) during the execution of a program. AFileStreamobject canrepositionitsfile-position pointer (which contains the byte number of the next byte to be read from or written to the file) toanyposition in the file. When aFileStreamobject is opened, itsfile-position pointeris set tobyte position
0(i.e., thebeginningof the file)
We now present a program that builds on the concepts employed in Fig. 17.11. Class
CreditInquiryForm(Fig. 17.12) is a credit-inquiry program that enables a credit manager Error-Prevention Tip 17.1
Open a file with theFileAccess.Readfile-open mode if its contents should not be mod- ified. This prevents unintentional modification of the contents.
to search for and display account information for those customers with credit balances (i.e., customers to whom the company owes money), zero balances (i.e., customers who do not owe the company money) and debit balances (i.e., customers who owe the com- pany money for previously received goods and services). We use aRichTextBoxin the pro- gram to display the account information.RichTextBoxes provide more functionality than regularTextBoxes—for example,RichTextBoxes offer method Findfor searching indi- vidual strings and methodLoadFilefor displaying file contents. ClassesRichTextBoxand
TextBoxboth inherit fromabstractclassSystem.Windows.Forms.TextBoxBase. In this example, we chose aRichTextBox, because it displays multiple lines of text by default, whereas a regularTextBoxdisplays only one. Alternatively, we could have specified that a
TextBoxobject displaymultiplelines of text by setting itsMultilineproperty totrue. The program displays buttons that enable a credit manager to obtain credit informa- tion. TheOpen Filebutton opens a file for gathering data. TheCredit Balancesbutton dis- plays a list of accounts that have credit balances, theDebit Balancesbutton displays a list of accounts that have debit balances and the Zero Balances button displays a list of accounts that have zero balances. TheDonebutton exits the app.
1 // Fig. 17.12: CreditInquiryForm.cs
2 // Read a file sequentially and display contents based on
3 // account type specified by user ( credit, debit or zero balances ).
4 using System;
5 using System.Windows.Forms;
6 using System.IO;
7 using BankLibrary;
8
9 namespace CreditInquiry 10 {
11 public partial class CreditInquiryForm : Form
12 {
13 14 15
16 // name of file that stores credit, debit and zero balances 17 private string fileName;
18
19 // parameterless constructor 20 public CreditInquiryForm()
21 {
22 InitializeComponent();
23 } // end constructor 24
25 // invoked when user clicks Open File button
26 private void openButton_Click( object sender, EventArgs e )
27 {
28 // create dialog box enabling user to open file 29 DialogResult result;
30
31 using ( OpenFileDialog fileChooser = new OpenFileDialog() )
32 {
Fig. 17.12 | Credit-inquiry program. (Part 1 of 5.)
private FileStream input; // maintains the connection to the file private StreamReader fileReader; // reads data from text file
17.7 Case Study: Credit Inquiry Program 697
33 34
35 } // end using
36
37 // exit event handler if user clicked Cancel 38 if ( result == DialogResult.OK )
39 {
40 // show error if user specified invalid file 41 if ( fileName == string.Empty )
42 MessageBox.Show( "Invalid File Name", "Error",
43 MessageBoxButtons.OK, MessageBoxIcon.Error );
44 else
45 {
46 // create FileStream to obtain read access to file 47
48 49
50 // set file from where data is read 51
52
53 // enable all GUI buttons, except for Open File button 54 openButton.Enabled = false;
55 creditButton.Enabled = true;
56 debitButton.Enabled = true;
57 zeroButton.Enabled = true;
58 } // end else
59 } // end if
60 } // end method openButton_Click 61
62 // invoked when user clicks credit balances, 63 // debit balances or zero balances button
64 private void getBalances_Click( object sender, System.EventArgs e )
65 {
66 // convert sender explicitly to object of type button 67 Button senderButton = ( Button ) sender;
68
69 // get text from clicked Button, which stores account type 70 string accountType = senderButton.Text;
71
72 // read and display file information
73 try
74 {
75 // go back to the beginning of the file 76
77
78 displayTextBox.Text = "The accounts are:\r\n";
79
80 // traverse file until end of file
81 while ( true )
82 {
83 string[] inputFields; // stores individual pieces of data 84 Record record; // store each Record as file is read 85 decimal balance; // store each Record's balance
Fig. 17.12 | Credit-inquiry program. (Part 2 of 5.)
result = fileChooser.ShowDialog();
fileName = fileChooser.FileName;
input = new FileStream( fileName, FileMode.Open, FileAccess.Read );
fileReader = new StreamReader( input );
input.Seek( 0, SeekOrigin.Begin );
86
87 // get next Record available in file 88
89
90 // when at the end of file, exit method
91 if ( inputRecord == null )
92 return;
93
94 inputFields = inputRecord.Split( ',' ); // parse input 95
96 // create Record from input
97 record = new Record(
98 Convert.ToInt32( inputFields[ 0 ] ), inputFields[ 1 ], 99 inputFields[ 2 ], Convert.ToDecimal(inputFields[ 3 ]));
100
101 // store record's last field in balance 102 balance = record.Balance;
103
104 // determine whether to display balance 105 if ( ShouldDisplay( balance, accountType ) )
106 {
107 // display record
108 string output = record.Account + "\t" +
109 record.FirstName + "\t" + record.LastName + "\t";
110
111 // display balance with correct monetary format 112 output += String.Format( "{0:F}", balance ) + "\r\n";
113
114 // copy output to screen
115 displayTextBox.AppendText( output );
116 } // end if
117 } // end while
118 } // end try
119 // handle exception when file cannot be read 120 catch ( IOException )
121 {
122 MessageBox.Show( "Cannot Read File", "Error",
123 MessageBoxButtons.OK, MessageBoxIcon.Error );
124 } // end catch
125 } // end method getBalances_Click 126
127 // determine whether to display given record
128 private bool ShouldDisplay( decimal balance, string accountType )
129 {
130 if ( balance > 0M )
131 {
132 // display credit balances
133 if ( accountType == "Credit Balances" )
134 return true;
135 } // end if
136 else if ( balance < 0M )
137 {
Fig. 17.12 | Credit-inquiry program. (Part 3 of 5.)
string inputRecord = fileReader.ReadLine();
17.7 Case Study: Credit Inquiry Program 699
138 // display debit balances
139 if ( accountType == "Debit Balances" )
140 return true;
141 } // end else if 142 else // balance == 0
143 {
144 // display zero balances
145 if ( accountType == "Zero Balances" )
146 return true;
147 } // end else 148
149 return false;
150 } // end method ShouldDisplay 151
152 // invoked when user clicks Done button
153 private void doneButton_Click( object sender, EventArgs e )
154 {
155 if ( input != null )
156 {
157 // close file and StreamReader
158 try
159 {
160 // close StreamReader and underlying file 161
162 } // end try
163 // handle exception if FileStream does not exist 164 catch ( IOException )
165 {
166 // notify user of error closing file
167 MessageBox.Show( "Cannot close file", "Error",
168 MessageBoxButtons.OK, MessageBoxIcon.Error );
169 } // end catch
170 } // end if
171
172 Application.Exit();
173 } // end method doneButton_Click 174 } // end class CreditInquiryForm 175 } // end namespace CreditInquiry
Fig. 17.12 | Credit-inquiry program. (Part 4 of 5.)
fileReader.Close();
a) GUI when the app first executes
When the user clicks the Open File button, the program calls the event handler
openButton_Click(lines 26–60). Line 31 creates anOpenFileDialog, and line 33 calls its Fig. 17.12 | Credit-inquiry program. (Part 5 of 5.)
b) Opening the clients.txtfile
c) Displaying accounts with credit balances
d) Displaying accounts with debit balances
e) Displaying accounts with zero balances