To retrieve data sequentially from a file, programs normally start from the beginning of the file, reading consecutively until the desired data is found. It sometimes is necessary to process a file sequentially several times (from the beginning of the file) during the execution of a program. A FileStream object can reposition its file-positionpointer (which contains the byte number of the next byte to be read from or written to the file) to any position in the file. When a FileStream object is opened, its file-position pointer is set to byte position 0 (i.e., the beginning of the file).
We now present a program that builds on the concepts employed in Fig. 17.6. Class CreditInquiryForm (Fig. 17.7) is a credit-inquiry program that enables a credit manager 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 company money for previously received goods and services). We use a RichTextBox in the program to display the account information. RichTextBoxes provide more functionality than regular TextBoxes—for example, RichTextBoxes offer method Find for searching individual strings and method LoadFile for displaying file contents. Classes RichTextBox and TextBox both inherit from abstract class System.Windows.Forms.TextBoxBase. In this example, we chose a RichTextBox, because it displays multiple lines of text by default, whereas a regular TextBox displays only one. Alternatively, we could have specified that a TextBox object display multiple lines of text by setting its Multiline property to true.
The program displays buttons that enable a credit manager to obtain credit information. The Open File button opens a file for gathering data. The Credit Balances button displays a list of accounts that have credit balances, the Debit Balances button displays a list of accounts that have debit balances and the Zero Balances button displays a list of accounts that have zero balances. The Done button exits the app.
When the user clicks the Open File button, the program calls the event handler openButton_Click (lines 23–60). Line 29 creates an OpenFileDialog, and line 31 calls its ShowDialog method to display the Open dialog, in which the user selects the file to open. Lines 47–48 create a FileStream object with read-only file access and assign it to reference input. Line 51 creates a StreamReader object that we use to read text from the FileStream.
When the user clicks Credit Balances, Debit Balances or Zero Balances, the program invokes method getBalances_Click (lines 64–116). Line 67 casts the sender parameter, which is an object reference to the control that generated the event, to a Button object. Line 70 extracts the Button object’s text, which the program uses to determine which type of accounts to display. Line 76 uses FileStream method Seek to reset the file-position pointer back to the beginning of the file. FileStream method Seek allows you to reset the file-position pointer by specifying the number of bytes it should be offset from the file’s beginning, end or current position. The part of the file you want to be offset from is chosen using constants from the SeekOrigin enumeration. In this case, our stream is offset by 0 bytes from the file’s beginning (SeekOrigin.Begin). Line 102 use private method ShouldDisplay (lines 119–135) to determine whether to display each record in the file. The while loop obtains each record by repeatedly calling StreamReader method ReadLine (line 85) and splitting the text into tokens (line 94) that are used to initialize object record (lines 97–99). Line 88 determines whether the file-position pointer has reached the end of the file, in which case ReadLine returns null. If so, the program returns from method getBalances_Click (line 90).