Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 17 – Files and Streams

Similar presentations


Presentation on theme: "Chapter 17 – Files and Streams"— Presentation transcript:

1 Chapter 17 – Files and Streams
Outline Introduction Data Hierarchy Files and Streams Classes File and Directory Creating a Sequential-Access File Reading Data from a Sequential-Access File Random-Access Files Creating a Random-Access File Writing Data Randomly to a Random-Access File Reading Data Sequentially from a Random-Access File Case Study: A Transaction-Processing Program

2 Variables and arrays only temporary
17.1 Introduction Variables and arrays only temporary Lost during garbage collection or when a program terminates Files used for long term storage Called persistent data This chapter deals with: Sequential-access files Random-access files File processing features Stream-input/output features

3 17.2 Data Hierarchy Data Hierarchy:
Gets more complex as you move along: Bit: either one or zero All data represented as combination of bits Easy for electronic devices to understand Byte: eight bits Character: in C# two bytes Character set: set of all characters used to program and represent data on a particular computer Field: composition of characters that convey a meaning Record: composition of several, related fields File: group of related records Record key: identifies record to a particular entity Sequential file: records stored in order of record-key

4 17.2 Data Hierarchy Randy Red Iris Orange Judy Green Tom Blue Sally
Black file record Field byte (ASCII for J) bit Fig Data hierarchy.

5 Files are sequential streams of bytes When file opened C#:
17.3 Files and Streams Files are sequential streams of bytes Ends with either an end-of-file marker or a specific byte When file opened C#: Creates an object Associates a stream with that object Three stream objects: Console.In: returns standard input stream object Console.Out: returns standard output stream object Console.Error: returns standard error stream object Namespace System.IO needed for file processing

6 BinaryFormatter: used to serialize and deserialize objects
17.3 Files and Streams BinaryFormatter: used to serialize and deserialize objects Serialize:converting an object into a format that can be written to a file without losing data Deserialize: Reading formatted text from a file and reconstructing the original object from it System.IO.Stream: allows representation of stream as bits FileStream: read to and write from sequential-access and random-access files MemoryStream:transfer of data directly to and from memory BufferedStream: uses buffer to transfer to memory

7 17.3 Files and Streams 1 2 3 4 5 6 7 8 9 n - 1 …… end of file marker
Fig C#’s view of an n-byte file.

8 17.4 Classes File and Directory
Information stored in files Files organized in directories Directory class used to manipulate directories File class used to manipulate files Only has static methods, cannot instantiate File objects

9 17.4 Classes File and Directory

10 17.4 Classes File and Directory

11 Textbox for input of file or directory name
1 // Fig 17.5: FileTest.cs 2 // Using classes File and Directory. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 using System.IO; 11 12 // displays contents of files and directories 13 public class FileTestForm : System.Windows.Forms.Form 14 { private System.Windows.Forms.Label directionsLabel; 16 private System.Windows.Forms.TextBox outputTextBox; private System.Windows.Forms.TextBox inputTextBox; 19 private System.ComponentModel.Container components = null; 21 [STAThread] static void Main() { Application.Run( new FileTestForm() ); } 27 // Visual Studio .NET generated code 29 // invoked when user presses key private void inputTextBox_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e ) { FileTest.cs Textbox for input of file or directory name Event handler for keystrokes

12 Test if key typed was enter
// determine whether user pressed Enter key if ( e.KeyCode == Keys.Enter ) { string fileName; // name of file or directory 38 // get user-specified file or directory fileName = inputTextBox.Text; 41 // determine whether fileName is a file if ( File.Exists( fileName ) ) { // get file's creation date, // modification date, etc. outputTextBox.Text = GetInformation( fileName ); 48 // display file contents through StreamReader try { // obtain reader and file contents StreamReader stream = new StreamReader( fileName ); outputTextBox.Text += stream.ReadToEnd(); } // handle exception if StreamReader is unavailable catch( IOException ) { MessageBox.Show( "File Error", "File Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 63 // determine whether fileName is a directory else if ( Directory.Exists( fileName ) ) { // array for directories string[] directoryList; Test if key typed was enter FileTest.cs Set fileName to what user typed See if fileName is an existing file If an existing file, get and output file information Create StreamReader to read text from file Call method ReadToEnd Test if fileName is existing directory

13 If it exists, get and output directory information FileTest.cs
69 // get directory's creation date, // modification date, etc. outputTextBox.Text = GetInformation( fileName ); 73 // obtain file/directory list of specified directory directoryList = Directory.GetDirectories( fileName ); 76 outputTextBox.Text += "\r\n\r\nDirectory contents:\r\n"; 79 // output directoryList contents for ( int i = 0; i < directoryList.Length; i++ ) outputTextBox.Text += directoryList[ i ] + "\r\n"; } else { // notify user that neither file nor directory exists MessageBox.Show( inputTextBox.Text + " does not exist", "File Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } // end if 92 } // end method inputTextBox_KeyDown 94 // get information on file or directory private string GetInformation( string fileName ) { // output that file or directory exists string information = fileName + " exists\r\n\r\n"; 100 // output when file or directory was created information += "Created: " + File.GetCreationTime( fileName ) + "\r\n"; If it exists, get and output directory information FileTest.cs Get subdirectories Output subdirectories If user input is not existing file or directory output error message Tell user file exists Get file creation information

14 Get last time file was modified
104 // output when file or directory was last modified information += "Last modified: " + File.GetLastWriteTime( fileName ) + "\r\n"; 108 // output when file or directory was last accessed information += "Last accessed: " + File.GetLastAccessTime( fileName ) + "\r\n" + "\r\n"; 112 return information; 114 } // end method GetInformation 116 117 } // end class FileTestForm Get last time file was modified FileTest.cs Get last time file was accessed Return file information

15 FileTest.cs Program Output

16 Used to store type and number of each file extension
1 // Fig 17.6: FileSearch.cs 2 // Using regular expressions to determine file types. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 using System.IO; 11 using System.Text.RegularExpressions; 12 using System.Collections.Specialized; 13 14 public class FileSearchForm : System.Windows.Forms.Form 15 { private System.Windows.Forms.Label directionsLabel; private System.Windows.Forms.Label directoryLabel; 18 private System.Windows.Forms.Button searchButton; 20 private System.Windows.Forms.TextBox outputTextBox; private System.Windows.Forms.TextBox inputTextBox; 23 private System.ComponentModel.Container components = null; 25 string currentDirectory = Directory.GetCurrentDirectory(); string[] directoryList; // subdirectories string[] fileArray; 29 // store extensions found and number found NameValueCollection found = new NameValueCollection(); 32 FileSearch.cs Used to store type and number of each file extension

17 Method to search recursively through directory path
[STAThread] static void Main() { Application.Run( new FileSearchForm() ); } 38 // Visual Studio .NET generated code 40 // invoked when user types in text box private void inputTextBox_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e ) { // determine whether user pressed Enter if ( e.KeyCode == Keys.Enter ) searchButton_Click( sender, e ); 48 } // end method inputTextBox_KeyDown 50 // invoked when user clicks "Search Directory" button private void searchButton_Click( object sender, System.EventArgs e ) { // check for user input; default is current directory if ( inputTextBox.Text != "" ) { // verify that user input is valid directory name if ( Directory.Exists( inputTextBox.Text ) ) { currentDirectory = inputTextBox.Text; 62 // reset input text box and update display directoryLabel.Text = "Current Directory:" + "\r\n" + currentDirectory; } FileSearch.cs Method to search recursively through directory path Test if valid directory

18 If directory does not exist display error
else { // show error if user does not specify valid directory MessageBox.Show( "Invalid Directory", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 74 // clear text boxes inputTextBox.Clear(); outputTextBox.Clear(); 78 // search directory SearchDirectory( currentDirectory ); 81 // summarize and print results foreach ( string current in found ) { outputTextBox.Text += "* Found " + found[ current ] + " " + current + " files.\r\n"; } 88 // clear output for new search found.Clear(); 91 } // end method searchButton_Click 93 // search directory using regular expression private void SearchDirectory( string currentDirectory ) { // search directory try { string fileName = ""; 101 FileSearch.cs If directory does not exist display error If valid directory, call SearchDirectory Display results of search

19 Define regularExpression as any file with extension FileSearch.cs
// regular expression for extensions matching pattern Regex regularExpression = new Regex( "[a-zA-Z0-9]+\\.(?<extension>\\w+)" ); 105 // stores regular-expression-match result Match matchResult; 108 string fileExtension; // holds file extensions 110 // number of files with given extension in directory int extensionCount; 113 // get directories directoryList = Directory.GetDirectories( currentDirectory ); 117 // get list of files in current directory fileArray = Directory.GetFiles( currentDirectory ); 120 // iterate through list of files foreach ( string myFile in fileArray ) { // remove directory path from file name fileName = myFile.Substring( myFile.LastIndexOf( "\\" ) + 1 ); 127 // obtain result for regular-expression search matchResult = regularExpression.Match( fileName ); 130 // check for match if ( matchResult.Success ) fileExtension = matchResult.Result( "${extension}" ); Define regularExpression as any file with extension FileSearch.cs Get subdirectories Get files of current directory Search directory and subdirectory for bak files Eliminate directory path to make comparison easier Test if bak file Store file extension

20 If not a match, store no extension
else fileExtension = "[no extension]"; 137 // store value from container if ( found[ fileExtension ] == null ) found.Add( fileExtension, "1" ); else { extensionCount = Int32.Parse( found[ fileExtension ] ) + 1; 145 found[ fileExtension ] = extensionCount.ToString(); } 148 // search for backup(.bak) files if ( fileExtension == "bak" ) { // prompt user to delete (.bak) file DialogResult result = MessageBox.Show( "Found backup file " + fileName + ". Delete?", "Delete Backup", MessageBoxButtons.YesNo, MessageBoxIcon.Question ); 158 // delete file if user clicked 'yes' if ( result == DialogResult.Yes ) { File.Delete( myFile ); 163 extensionCount = Int32.Parse( found[ "bak" ] ) - 1; 166 If not a match, store no extension FileSearch.cs Test if first time extension was found If first time, add extension to list If not first time, increment extension counter Test if bak file Ask if user wants to delete bak file If yes, delete file, decrement count

21 Search every subdirectory
found[ "bak" ] = extensionCount.ToString(); } } } 171 // recursive call to search files in subdirectory foreach ( string myDirectory in directoryList ) SearchDirectory( myDirectory ); } 176 // handle exception if files have unauthorized access catch( UnauthorizedAccessException ) { MessageBox.Show( "Some files may not be visible" + " due to permission settings", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information ); } 184 } // end method SearchDirectory 186 187 } // end class FileSearchForm FileSearch.cs Search every subdirectory

22 FileSearch.cs Program Output

23 17.5 Creating a Sequential-Access File
Programmers have to structure files to meet the requirements of applications

24 BankUI.cs Textboxes Labels 1 // Fig 17.7: BankUI.cs
2 // A reusable windows form for the examples in this chapter. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 11 public class BankUIForm : System.Windows.Forms.Form 12 { private System.ComponentModel.Container components = null; 14 public System.Windows.Forms.Label accountLabel; public System.Windows.Forms.TextBox accountTextBox; 17 public System.Windows.Forms.Label firstNameLabel; public System.Windows.Forms.TextBox firstNameTextBox; 20 public System.Windows.Forms.Label lastNameLabel; public System.Windows.Forms.TextBox lastNameTextBox; 23 public System.Windows.Forms.Label balanceLabel; public System.Windows.Forms.TextBox balanceTextBox; 26 // number of TextBoxes on Form' protected int TextBoxCount = 4; 29 BankUI.cs Labels Textboxes

25 Method to clear textboxes
// enumeration constants specify TextBox indices public enum TextBoxIndices { ACCOUNT, FIRST, LAST, BALANCE 37 } // end enum 39 [STAThread] static void Main() { Application.Run( new BankUIForm() ); } 45 // Visual Studio .NET generated code 47 // clear all TextBoxes public void ClearTextBoxes() { // iterate through every Control on form for ( int i = 0; i < Controls.Count; i++ ) { Control myControl = Controls[ i ]; // get control 55 // determine whether Control is TextBox if ( myControl is TextBox ) { // clear Text property (set to empty strng) myControl.Text = ""; } } 63 } // end method ClearTextBoxes BankUI.cs Method to clear textboxes

26 Method to set values of textboxes
65 // set text box values to string array values public void SetTextBoxValues( string[] values ) { // determine whether string array has correct length if ( values.Length != TextBoxCount ) { // throw exception if not correct length throw( new ArgumentException( "There must be " + (TextBoxCount + 1) + " strings in the array" ) ); } 76 // set array values if array has correct length else { // set array values to text box values accountTextBox.Text = values[ ( int )TextBoxIndices.ACCOUNT ]; firstNameTextBox.Text = values[ ( int )TextBoxIndices.FIRST ]; lastNameTextBox.Text = values[ ( int )TextBoxIndices.LAST ]; balanceTextBox.Text = values[ ( int )TextBoxIndices.BALANCE ]; } 90 } // end method SetTextBoxValues 92 // return text box values as string array public string[] GetTextBoxValues() { string[] values = new string[ TextBoxCount ]; 97 Method to set values of textboxes BankUI.cs Method to get the values of textboxes

27 BankUI.cs Program Output
// copy text box fields to string array values[ ( int )TextBoxIndices.ACCOUNT ] = accountTextBox.Text; values[ ( int )TextBoxIndices.FIRST ] = firstNameTextBox.Text; values[ ( int )TextBoxIndices.LAST ] = lastNameTextBox.Text; values[ ( int )TextBoxIndices.BALANCE ] = balanceTextBox.Text; 107 return values; 109 } // end method GetTextBoxValues 111 112 } // end class BankUIForm BankUI.cs Program Output

28 Set members to parameters
1 // Fig. 17.8: Record.cs 2 // Serializable class that represents a data record. 3 4 using System; 5 6 [Serializable] 7 public class Record 8 { private int account; private string firstName; private string lastName; private double balance; 13 // default constructor sets members to default values public Record() : this( 0, "", "", 0.0 ) { } 18 // overloaded constructor sets members to parameter values public Record( int accountValue, string firstNameValue, string lastNameValue, double balanceValue ) { Account = accountValue; FirstName = firstNameValue; LastName = lastNameValue; Balance = balanceValue; 27 } // end constructor 29 Record.cs Tells compiler objects of class Record can be represented as a set of bits Data to go into record Sets members to 0 Set members to parameters

29 Record.cs Accessor methods 30 // property Account
public int Account { get { return account; } 37 set { account = value; } 42 } // end property Account 44 // property FirstName public string FirstName { get { return firstName; } 52 set { firstName = value; } 57 } // end property FirstName 59 Accessor methods Record.cs

30 Record.cs Accessor methods 60 // property LastName
public string LastName { get { return lastName; } 67 set { lastName = value; } 72 } // end property LastName 74 // property Balance public double Balance { get { return balance; } 82 set { balance = value; } 87 } // end property Balance 89 90 } // end class Record Accessor methods Record.cs

31 1 // Fig 17.9: CreateSequentialAccessFile.cs
2 // Creating a sequential-access file. 3 4 // C# namespaces 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 using System.Data; 11 using System.IO; 12 using System.Runtime.Serialization.Formatters.Binary; 13 using System.Runtime.Serialization; 14 15 // Deitel namespace 16 using BankLibrary; 17 18 public class CreateFileForm : BankUIForm 19 { private System.Windows.Forms.Button saveButton; private System.Windows.Forms.Button enterButton; private System.Windows.Forms.Button exitButton; 23 private System.ComponentModel.Container components = null; 25 // serializes Record in binary format private BinaryFormatter formatter = new BinaryFormatter(); 28 // stream through which serializable data is written to file private FileStream output; 31 CreateSequentialAccessFile.cs

32 Instantiate SaveFileDialog object
[STAThread] static void Main() { Application.Run( new CreateFileForm() ); } 37 // Visual Studio .NET generated code 39 // invoked when user clicks Save button private void saveButton_Click( object sender, System.EventArgs e ) { // create dialog box enabling user to save file SaveFileDialog fileChooser = new SaveFileDialog(); DialogResult result = fileChooser.ShowDialog(); string fileName; // name of file to save data 48 // allow user to create file fileChooser.CheckFileExists = false; 51 // exit event handler if user clicked "Cancel" if ( result == DialogResult.Cancel ) return; 55 // get specified file name fileName = fileChooser.FileName; 58 // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show( "Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); CreateSequentialAccessFile.cs Instantiate SaveFileDialog object Show SaveFileDialog Test if user canceled save Get file name to save to

33 Instantiate output stream with write permission
else { // save file via FileStream if user specified valid file try { // open file with write access output = new FileStream( fileName, FileMode.OpenOrCreate, FileAccess.Write ); 71 // disable Save button and enable Enter button saveButton.Enabled = false; enterButton.Enabled = true; } 76 // handle exception if file does not exist catch ( FileNotFoundException ) { // notify user if file does not exist MessageBox.Show( "File Does Not Exist", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } } // end method saveButton_Click 86 // invoke when user clicks Enter button private void enterButton_Click( object sender, System.EventArgs e ) { // store TextBox values string array string[] values = GetTextBoxValues(); 93 // Record containing TextBox values to serialize Record record = new Record(); 96 CreateSequentialAccessFile.cs Instantiate output stream with write permission Method to save data when user clicks enter

34 Store TextBox fields in record
// determine whether TextBox account field is empty if ( values[ ( int )TextBoxIndices.ACCOUNT ] != "" ) { // store TextBox values in Record and serialize Record try { // get account number value from TextBox int accountNumber = Int32.Parse( values[ ( int )TextBoxIndices.ACCOUNT ] ); 106 // determine whether accountNumber is valid if ( accountNumber > 0 ) { // store TextBox fields in Record record.Account = accountNumber; record.FirstName = values[ ( int )TextBoxIndices.FIRST ]; record.LastName = values[ ( int )TextBoxIndices.LAST ]; record.Balance = Double.Parse( values[ ( int )TextBoxIndices.BALANCE ] ); 118 // write Record to FileStream (serialize object) formatter.Serialize( output, record ); } else { // notify user if invalid account number MessageBox.Show( "Invalid Account Number", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 129 CreateSequentialAccessFile.cs Store TextBox fields in record Write data to file

35 Catch block if user input invalid data
// notify user if error occurs in serialization catch( SerializationException ) { MessageBox.Show( "Error Writing to File", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } 136 // notify user if error occurs regarding parameter format catch( FormatException ) { MessageBox.Show( "Invalid Format", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 144 ClearTextBoxes(); // clear TextBox values 146 } // end method enterButton_Click 148 // invoked when user clicks Exit button private void exitButton_Click( object sender, System.EventArgs e ) { // determine whether file exists if ( output != null ) { // close file try { output.Close(); } 161 CreateSequentialAccessFile.cs Catch block if user input invalid data Close FileStream

36 CreateSequentialAccessFile.cs Program Output
// notify user of error closing file catch( IOException ) { MessageBox.Show( "Cannot close file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 169 Application.Exit(); 171 } // end method exitButton_Click 173 174 } // end class CreateFileForm CreateSequentialAccessFile.cs Program Output Exit program BankUI graphical user interface

37 CreateSequentialAccessFile.cs Program Output
SaveFileDialogue Files and directories

38 CreateSequentialAccessFile.cs Program Output

39 CreateSequentialAccessFile.cs Program Output

40 CreateSequentialAccessFile.cs Program Output

41 17.5 Creating a Sequential-Access File

42 17.6 Reading Data from a Sequential-Access File
Read data sequentially from a file Programs usually start at beginning of file and read data consecutively until the desired data is found Sometimes necessary to do this several times during execution of a program File-position pointer: Points to next byte to be read from or written to file Can be repositioned to any point in file RichTextBox: LoadFile: method to display file contents Find: method for searching individual strings Can display multiple lines of text

43 1 // Fig. 17.11: ReadSequentialAccessFile.cs
2 // Reading a sequential-access file. 3 4 // C# namespaces 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 using System.Data; 11 using System.IO; 12 using System.Runtime.Serialization.Formatters.Binary; 13 using System.Runtime.Serialization; 14 15 // Deitel namespaces 16 using BankLibrary; 17 18 public class ReadSequentialAccessFileForm : BankUIForm 19 { System.Windows.Forms.Button openButton; System.Windows.Forms.Button nextButton; 22 private System.ComponentModel.Container components = null; 24 // stream through which serializable data are read from file private FileStream input; 27 // object for deserializing Record in binary format private BinaryFormatter reader = new BinaryFormatter(); 30 [STAThread] static void Main() { Application.Run( new ReadSequentialAccessFileForm() ); } ReadSequentialAccessFile.cs

44 Instantiate OpenFilelDialog
36 // Visual Studio .NET generated code 38 // invoked when user clicks Open button private void openButton_Click( object sender, System.EventArgs e ) { // create dialog box enabling user to open file OpenFileDialog fileChooser = new OpenFileDialog(); DialogResult result = fileChooser.ShowDialog(); string fileName; // name of file containing data 47 // exit event handler if user clicked Cancel if ( result == DialogResult.Cancel ) return; 51 // get specified file name fileName = fileChooser.FileName; ClearTextBoxes(); 55 // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show( "Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); else { // create FileStream to obtain read access to file input = new FileStream( fileName, FileMode.Open, FileAccess.Read ); 65 // enable next record button nextButton.Enabled = true; } 69 } // end method openButton_Click ReadSequentialAccessFile.cs Instantiate OpenFilelDialog Display OpenFileDialog Create FileStream object for input with read only perimission

45 Method to view next record
71 // invoked when user clicks Next button private void nextButton_Click( object sender, System.EventArgs e ) { // deserialize Record and store data in TextBoxes try { // get next Record available in file Record record = ( Record )reader.Deserialize( input ); 82 // store Record values in temporary string array string[] values = new string[] { record.Account.ToString(), record.FirstName.ToString(), record.LastName.ToString(), record.Balance.ToString() }; 89 // copy string array values to TextBox values SetTextBoxValues( values ); } 93 // handle exception when no Records in file catch( SerializationException ) {\ // close FileStream if no Records in file input.Close(); 99 // enable Open Record button openButton.Enabled = true; 102 // disable Next Record button nextButton.Enabled = false; 105 Method to view next record ReadSequentialAccessFile.cs Deserialize and cast next record Display Record in TextBoxes Exception thrown when there are no more records Close FileStream

46 ReadSequentialAccessFile.cs Program Output
ClearTextBoxes(); 107 // notify user if no Records in file MessageBox.Show( "No more records in file", "", MessageBoxButtons.OK, MessageBoxIcon.Information ); } 112 } // end method nextButton_Click 114 115 } // end class ReadSequentialAccessFileForm ReadSequentialAccessFile.cs Program Output Tell user there are no more records

47 ReadSequentialAccessFile.cs Program Output

48 ReadSequentialAccessFile.cs Program Output

49 ReadSequentialAccessFile.cs Program Output

50 ReadSequentialAccessFile.cs Program Output

51 CreditInquiry.cs 1 // Fig. 17.12: CreditInquiry.cs
2 // Read a file sequentially and display contents based on 3 // account type specified by user (credit, debit or zero balances). 4 5 // C# namespaces 6 using System; 7 using System.Drawing; 8 using System.Collections; 9 using System.ComponentModel; 10 using System.Windows.Forms; 11 using System.Data; 12 using System.IO; 13 using System.Runtime.Serialization.Formatters.Binary; 14 using System.Runtime.Serialization; 15 16 // Deitel namespaces 17 using BankLibrary; 18 19 public class CreditInquiryForm : System.Windows.Forms.Form 20 { private System.Windows.Forms.RichTextBox displayTextBox; 22 private System.Windows.Forms.Button doneButton; private System.Windows.Forms.Button zeroButton; private System.Windows.Forms.Button debitButton; private System.Windows.Forms.Button creditButton; private System.Windows.Forms.Button openButton; 28 private System.ComponentModel.Container components = null; 30 // stream through which serializable data are read from file private FileStream input; 33 // object for deserializing Record in binary format BinaryFormatter reader = new BinaryFormatter(); CreditInquiry.cs

52 User clicked open button
36 // name of file that stores credit, debit and zero balances private string fileName; 39 [STAThread] static void Main() { Application.Run( new CreditInquiryForm() ); } 45 // Visual Studio .NET generated code 47 // invoked when user clicks Open File button private void openButton_Click( object sender, System.EventArgs e ) { // create dialog box enabling user to open file OpenFileDialog fileChooser = new OpenFileDialog(); DialogResult result = fileChooser.ShowDialog(); 55 // exit event handler if user clicked Cancel if ( result == DialogResult.Cancel ) return; 59 // get name from user fileName = fileChooser.FileName; 62 // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show( "Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); CreditInquiry.cs User clicked open button Instantiate OpenFilelDialog Show OpenFileDialog

53 Button click event handler
else { // enable all GUI buttons, except for Open file button openButton.Enabled = false; creditButton.Enabled = true; debitButton.Enabled = true; zeroButton.Enabled = true; } 75 } // end method openButton_Click 77 // invoked when user clicks credit balances, // debit balances or zero balances button private void get_Click( object sender, System.EventArgs e ) { // convert sender explicitly to object of type button Button senderButton = ( Button )sender; 84 // get text from clicked Button, which stores account type string accountType = senderButton.Text; 87 // read and display file information try { // close file from previous operation if ( input != null ) input.Close(); 94 // create FileStream to obtain read access to file input = new FileStream( fileName, FileMode.Open, FileAccess.Read ); 98 displayTextBox.Text = "The accounts are:\r\n"; 100 CreditInquiry.cs Button click event handler Reference to object that sent event Get text from clicked button Create read only FileStream for input

54 While loop to read from file
// traverse file until end of file while ( true ) { // get next Record available in file Record record = ( Record )reader.Deserialize( input ); 106 // store record's last field in balance Double balance = record.Balance; 109 // determine whether to display balance if ( ShouldDisplay( balance, accountType ) ) { // display record string output = record.Account + "\t" + record.FirstName + "\t" + record.LastName + new string( ' ', 6 ) + "\t"; 117 // display balance with correct monetary format output += String.Format( "{0:F}", balance ) + "\r\n"; 121 // copy output to screen displayTextBox.Text += output; } } } 127 // handle exception when file cannot be closed catch( IOException ) { MessageBox.Show( "Cannot Close File", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } 134 While loop to read from file CreditInquiry.cs Read input from file

55 No more records exception CreditInquiry.cs
// handle exception when no more records catch( SerializationException ) { // close FileStream if no Records in file input.Close(); } 141 } // end method get_Click 143 // determine whether to display given record private bool ShouldDisplay( double balance, string accountType ) { if ( balance > 0 ) { // display credit balances if ( accountType == "Credit Balances" ) return true; } 153 else if ( balance < 0 ) { // display debit balances if ( accountType == "Debit Balances" ) return true; } 160 else // balance == 0 { // display zero balances if ( accountType == "Zero Balances" ) return true; } 167 No more records exception CreditInquiry.cs Close FileStream Method to determine whether to display each record in file

56 Done button clicked event handler
return false; 169 } // end method ShouldDisplay 171 // invoked when user clicks Done button private void doneButton_Click( object sender, System.EventArgs e ) { // determine whether file exists if ( input != null ) { // close file try { input.Close(); } 184 // handle exception if FileStream does not exist catch( IOException ) { // notify user of error closing file MessageBox.Show( "Cannot close file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 193 Application.Exit(); 195 } // end method doneButton_Click 197 198 } // end class CreditInquiryForm CreditInquiry.cs Done button clicked event handler

57 CreditInquiry.cs Program Output

58 CreditInquiry.cs Program Output

59 Allows instant access to information
17.7 Random-Access Files Allows instant access to information Individual records can be accessed directly without searching through large numbers of other records Must be implemented through the application Easiest when all records are a fixed length Data can be inserted without destroying other data in file Records can be updated without rewriting the entire file Cannot serialize Won’t guarantee a fixed-length record size

60 17.7 Random-Access Files 100 200 300 400 500 100 bytes byte offsets
100 200 300 400 500 100 bytes byte offsets Fig Random-access file with fixed-length records.

61 Constant to hold record length
1 // Fig : RandomAccessRecord.cs 2 // Data-record class for random-access applications. 3 4 using System; 5 6 public class RandomAccessRecord 7 { // length of firstName and lastName private const int CHAR_ARRAY_LENGTH = 15; 10 private const int SIZE_OF_CHAR = 2; private const int SIZE_OF_INT32 = 4; private const int SIZE_OF_DOUBLE = 8; 14 // length of record public const int SIZE = SIZE_OF_INT32 + * ( SIZE_OF_CHAR * CHAR_ARRAY_LENGTH ) + SIZE_OF_DOUBLE; 18 // record data private int account; private char[] firstName = new char[ CHAR_ARRAY_LENGTH ]; private char[] lastName = new char[ CHAR_ARRAY_LENGTH ]; private double balance; 24 // default constructor sets members to default values public RandomAccessRecord() : this( 0, "", "", 0.0 ) { } 29 RandomAccessRecord.cs Constant to hold record length Private members for data storage Set members to default value

62 Set records to parameter values RandomAccessRecord.cs
// overloaded counstructor sets members to parameter values public RandomAccessRecord( int accountValue, string firstNameValue, string lastNameValue, double balanceValue ) { Account = accountValue; FirstName = firstNameValue; LastName = lastNameValue; Balance = balanceValue; 39 } // end constructor 41 // property Account public int Account { get { return account; } 49 set { account = value; } 54 } // end property Account 56 // property FirstName public string FirstName { get { return new string( firstName ); } 64 Set records to parameter values RandomAccessRecord.cs Account accessor methods First name accessor methods

63 Set accessor assures length is only 15 characters
{ // determine length of string parameter int stringSize = value.Length; 69 // firstName string representation string firstNameString = value; 72 // append spaces to string parameter if too short if ( CHAR_ARRAY_LENGTH >= stringSize ) { firstNameString = value + new string( ' ', CHAR_ARRAY_LENGTH - stringSize ); } else { // remove characters from string parameter if too long firstNameString = value.Substring( 0, CHAR_ARRAY_LENGTH ); } 85 // convert string parameter to char array firstName = firstNameString.ToCharArray(); 88 } // end set 90 } // end property FirstName 92 // property LastName public string LastName { get { return new string( lastName ); } Set accessor assures length is only 15 characters Get length of string RandomAccessRecord.cs Add spaces if length is less then 15 characters Remove characters if length is more then 15 characters Last name accessor methods

64 Set accessor assures length of 15 characters
100 set { // determine length of string parameter int stringSize = value.Length; 105 // lastName string representation string lastNameString = value; 108 // append spaces to string parameter if too short if ( CHAR_ARRAY_LENGTH >= stringSize ) { lastNameString = value + new string( ' ', CHAR_ARRAY_LENGTH - stringSize ); } else { // remove characters from string parameter if too long lastNameString = value.Substring( 0, CHAR_ARRAY_LENGTH ); } 121 // convert string parameter to char array lastName = lastNameString.ToCharArray(); 124 } // end set 126 } // end property LastName 128 Set accessor assures length of 15 characters Get name length RandomAccessRecord.cs Add spaces if length is less then 15 characters Remove characters if length is more then 15 characters

65 Balance accessor methods RandomAccessRecord.cs
// property Balance public double Balance { get { return balance; } 136 set { balance = value; } 141 } // end property Balance 143 144 } // end class RandomAccessRecord Balance accessor methods RandomAccessRecord.cs

66 17.8 Creating a Random-Access File
Use class BinaryWriter instead of serialization By attaching a FileStream to it, bytes can be written directly to a file

67 Save file to disk by invoking method SaveFile
1 // Fig : CreateRandomAccessFile.cs 2 // Creating a random file. 3 4 // C# namespaces 5 using System; 6 using System.IO; 7 using System.Windows.Forms; 8 9 // Deitel namespaces 10 using BankLibrary; 11 12 class CreateRandomAccessFile 13 { // number of records to write to disk private const int NUMBER_OF_RECORDS = 100; 16 [STAThread] static void Main(string[] args) { // create random file, then save to disk CreateRandomAccessFile file = new CreateRandomAccessFile(); file.SaveFile(); 23 } // end method Main 25 // write records to disk private void SaveFile() { // record for writing to disk RandomAccessRecord blankRecord = new RandomAccessRecord(); 31 // stream through which serializable data are written to file FileStream fileOutput = null; 34 CreateRandomAccessFile.cs Create a random file Save file to disk by invoking method SaveFile SaveFile method Create blank record

68 Instantiate FileStream with user selected file
// stream for writing bytes to file BinaryWriter binaryOutput = null; 37 // create dialog box enabling user to save file SaveFileDialog fileChooser = new SaveFileDialog(); DialogResult result = fileChooser.ShowDialog(); 41 // get file name from user string fileName = fileChooser.FileName; 44 // exit event handler if user clicked Cancel if ( result == DialogResult.Cancel ) return; 48 // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show("Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); else { // write records to file try { // create FileStream to hold records fileOutput = new FileStream( fileName, FileMode.Create, FileAccess.Write ); 61 // set length of file fileOutput.SetLength( RandomAccessRecord.SIZE * NUMBER_OF_RECORDS ); 65 // create object for writing bytes to file binaryOutput = new BinaryWriter( fileOutput ); 68 Create and display SaveFileDialog so user can specify file name and location CreateRandomAccessFile.cs Instantiate FileStream with user selected file Set length of FileStream to the size of a recod times the number of records Pass FileStream to BinaryWriter to write bytes directly to file

69 Move file position pointer to next write location
// write empty records to file for ( int i = 0; i < NUMBER_OF_RECORDS; i++ ) { // set file position pointer in file fileOutput.Position = i * RandomAccessRecord.SIZE; 74 // write blank record to file binaryOutput.Write( blankRecord.Account ); binaryOutput.Write( blankRecord.FirstName ); binaryOutput.Write( blankRecord.LastName ); binaryOutput.Write( blankRecord.Balance ); } 81 // notify user of success MessageBox.Show("File Created", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); } 86 // handle exception if error occurs during writing catch( IOException ) { // notify user of error MessageBox.Show( "Cannot write to file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 95 Create 100 empty records CreateRandomAccessFile.cs Move file position pointer to next write location Write data to file

70 CreateRandomAccessFile.cs Program Output
// close FileStream if ( fileOutput == null ) fileOutput.Close(); 99 // close BinaryWriter if ( binaryOutput == null ) binaryOutput.Close(); 103 } // end method SaveFile 105 } // end class CreateRandomAccessFile Close Filestream CreateRandomAccessFile.cs Program Output Close BinaryWriter

71 17.9 Writing Data Randomly to a Random-Access File

72 WriteRandomAccessFile.cs 1 // Fig 17.16: WriteRandomAccessFile.cs
2 // Write data to a random-access file. 3 4 // C# namespaces 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 using System.Data; 11 using System.IO; 12 13 // Deitel namespaces 14 using BankLibrary; 15 16 public class WriteRandomAccessFileForm : BankUIForm 17 { private System.Windows.Forms.Button openButton; private System.Windows.Forms.Button enterButton; 20 private System.ComponentModel.Container components = null; 22 // number of RandomAccessRecords to write to disk private const int NUMBER_OF_RECORDS = 100; 25 // stream through which data are written to file private FileStream fileOutput; 28 // stream for writing bytes to file private BinaryWriter binaryOutput; 31 WriteRandomAccessFile.cs

73 Open Button clicked event handler
[STAThread] static void Main() { Application.Run( new WriteRandomAccessFileForm() ); } 37 // Visual Studio .NET generated code 39 // invoked when user clicks Open button private void openButton_Click( object sender, System.EventArgs e ) { // create dialog box enabling user to open file OpenFileDialog fileChooser = new OpenFileDialog(); DialogResult result = fileChooser.ShowDialog(); 47 // get file name from user string fileName = fileChooser.FileName; 50 // exit event handler if user clicked Cancel if ( result == DialogResult.Cancel ) return; 54 // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show("Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); else { // open file if file already exists try { // create FileStream to hold records fileOutput = new FileStream( fileName, FileMode.Open, FileAccess.Write ); WriteRandomAccessFile.cs Open Button clicked event handler Instantiate and show OpenFileDialog so user can choose file to write to Create write only FileStream with user selected file for output

74 Create BinaryWriter to write directly to file
67 // create object for writing bytes to file binaryOutput = new BinaryWriter( fileOutput ); 70 // disable Open button and enable Enter button openButton.Enabled = false; enterButton.Enabled = true; } 75 // notify user if file does not exist catch( IOException ) { MessageBox.Show("File Does Not Exits", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 83 } // end method openButton_Click 85 // invoked when user clicks Enter button private void enterButton_Click( object sender, System.EventArgs e ) { // TextBox values string array string[] values = GetTextBoxValues(); 92 // determine whether TextBox account field is empty if ( values[ ( int )TextBoxIndices.ACCOUNT ] != "" ) { // write record to file at appropriate position try { // get account number value from TextBox int accountNumber = Int32.Parse( values[ ( int )TextBoxIndices.ACCOUNT ] ); Create BinaryWriter to write directly to file WriteRandomAccessFile.cs Enter clicked event handler, writes data entered to file Retrieve data from text boxes

75 Test if accountNumer is valid
102 // determine whether accountNumber is valid if ( accountNumber > 0 && accountNumber <= NUMBER_OF_RECORDS ) { // move file position pointer fileOutput.Seek( ( accountNumber - 1 ) * RandomAccessRecord.SIZE, SeekOrigin.Begin ); 110 // write data to file binaryOutput.Write( accountNumber ); binaryOutput.Write( values[ ( int )TextBoxIndices.FIRST ] ); binaryOutput.Write( values[ ( int )TextBoxIndices.LAST ] ); binaryOutput.Write( Double.Parse( values[ ( int )TextBoxIndices.BALANCE ] ) ); } else { // notify user if invalid account number MessageBox.Show("Invalid Account Number", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 127 // handle number-format exception Test if accountNumer is valid WriteRandomAccessFile.cs Move file position pointer Write data to file using BinaryWriter

76 WriteRandomAccessFile.cs Program Output
catch( FormatException ) { // notify user if error occurs when formatting numbers MessageBox.Show("Invalid Balance", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 136 ClearTextBoxes(); // clear text box values 138 } // end method enterButton_Click 140 141 } // end class WriteRandomAccessFileForm WriteRandomAccessFile.cs Program Output

77 WriteRandomAccessFile.cs Program Output

78 WriteRandomAccessFile.cs Program Output

79 WriteRandomAccessFile.cs Program Output

80 17.10 Reading Data Sequentially from a Random-Access File
Use class BinaryReader instead of deserialization By attaching a FileStream to it, bytes can be read directly from a file

81 ReadRandomAccessFile.cs 1 // Fig 17.17: ReadRandomAccessFile.cs
2 // Reads and displays random-access file contents. 3 4 // C# namespaces 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 using System.Data; 11 using System.IO; 12 13 // Deitel namespaces 14 using BankLibrary; 15 16 public class ReadRandomAccessFileForm : BankUIForm 17 { private System.Windows.Forms.Button openButton; private System.Windows.Forms.Button nextButton; 20 private System.ComponentModel.Container components = null; 22 // stream through which data are read from file private FileStream fileInput; 25 // stream for reading bytes from file private BinaryReader binaryInput; 28 // index of current record to be displayed private int currentRecordIndex; 31 ReadRandomAccessFile.cs

82 Open Button clicked event handler
[STAThread] static void Main() { Application.Run( new ReadRandomAccessFileForm() ); } 37 // Visual Studio .NET generated code 39 // invoked when user clicks Open button private void openButton_Click( object sender, System.EventArgs e ) { // create dialog box enabling user to open file OpenFileDialog fileChooser = new OpenFileDialog(); DialogResult result = fileChooser.ShowDialog(); 47 // get file name from user string fileName = fileChooser.FileName; 50 // exit eventhandler if user clicked Cancel if ( result == DialogResult.Cancel ) return; 54 // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show( "Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); else { // create FileStream to obtain read access to file fileInput = new FileStream( fileName, FileMode.Open, FileAccess.Read ); 64 ReadRandomAccessFile.cs Open Button clicked event handler Instantiate and show OpenFileDialog so user can choose file to read from Create FileStream with user selected file

83 Create BinaryReader to read from file ReadRandomAccessFile.cs
// use FileStream for BinaryWriter to read bytes from file binaryInput = new BinaryReader( fileInput ); 67 openButton.Enabled = false; // disable Open button nextButton.Enabled = true; // enable Next button 70 currentRecordIndex = 0; ClearTextBoxes(); } 74 } // end method openButton_Click 76 // invoked when user clicks Next button private void nextButton_Click( object sender, System.EventArgs e ) { // record to store file data RandomAccessRecord record = new RandomAccessRecord(); 83 // read record and store data in TextBoxes try { string[] values; // for storing TextBox values 88 // get next record available in file while( record.Account == 0 ) { // set file position pointer to next record in file fileInput.Seek( currentRecordIndex * RandomAccessRecord.SIZE, 0 ); 95 currentRecordIndex += 1; 97 Create BinaryReader to read from file ReadRandomAccessFile.cs Next button clicked event handler Instantiate record to store data Read from file until a nonzero account number is reached Move file position pointer

84 Use BinaryReader to store file data in record ReadRandomAccessFile.cs
// read data from record record.Account = binaryInput.ReadInt32(); record.FirstName = binaryInput.ReadString(); record.LastName = binaryInput.ReadString(); record.Balance = binaryInput.ReadDouble(); } 104 // store record values in temporary string array values = new string[] { record.Account.ToString(), record.FirstName, record.LastName, record.Balance.ToString() }; 111 // copy string array values to TextBox values SetTextBoxValues( values ); } 115 // handle exception when no records in file catch( IOException ) { // close streams if no records in file fileInput.Close(); binaryInput.Close(); 122 openButton.Enabled = true; // enable Open button nextButton.Enabled = false; // disable Next button ClearTextBoxes(); 126 Use BinaryReader to store file data in record ReadRandomAccessFile.cs Display records in TextBoxes No more records exception handler Close FileStream and BinaryReader

85 ReadRandomAccessFile.cs Program Output
// notify user if no records in file MessageBox.Show("No more records in file", "", MessageBoxButtons.OK, MessageBoxIcon.Information); } 131 } // end method nextButton_Click 133 134 } // end class ReadRandomAccessFileForm Tell user there are no more records ReadRandomAccessFile.cs Program Output

86 ReadRandomAccessFile.cs Program Output

87 ReadRandomAccessFile.cs Program Output

88 ReadRandomAccessFile.cs Program Output

89 ReadRandomAccessFile.cs Program Output

90 17.11 Case Study: A Transaction-Processing Program
Maintains a bank’s account information Users can add new accounts, update existing accounts and delete accounts Class Transaction Acts as a proxy: Handles all transactions so objects do not have to Allows abstraction

91 Method to create or open file
1 // Fig : Transaction.cs 2 // Handles record transactions. 3 4 // C# namespaces 5 using System; 6 using System.IO; 7 using System.Windows.Forms; 8 9 // Deitel namespaces 10 using BankLibrary; 11 12 public class Transaction 13 { // number of records to write to disk private const int NUMBER_OF_RECORDS = 100; 16 // stream through which data move to and from file private FileStream file; 19 // stream for reading bytes from file private BinaryReader binaryInput; 22 // stream for writing bytes to file private BinaryWriter binaryOutput; 25 // create/open file containing empty records public void OpenFile( string fileName ) { // write empty records to file try { // create FileStream from new file or existing file file = new FileStream( fileName, FileMode.OpenOrCreate ); 34 Transaction.cs Method to create or open file Create FileStream from new or existing file

92 Create BinaryWriter and BinaryReader from FileStream
// use FileStream for BinaryWriter to read bytes from file binaryInput = new BinaryReader( file ); 37 // use FileStream for BinaryWriter to write bytes to file binaryOutput = new BinaryWriter( file ); 40 // determine whether file has just been created if ( file.Length == 0 ) { // record to be written to file RandomAccessRecord blankRecord = new RandomAccessRecord(); 47 // new record can hold NUMBER_OF_RECORDS records file.SetLength( RandomAccessRecord.SIZE * NUMBER_OF_RECORDS ); 51 // write blank records to file for ( int i = 0; i < NUMBER_OF_RECORDS; i++ ) { // move file-position pointer to next position file.Position = i * RandomAccessRecord.SIZE; 57 // write blank record to file binaryOutput.Write( blankRecord.Account ); binaryOutput.Write( blankRecord.FirstName ); binaryOutput.Write( blankRecord.LastName ); binaryOutput.Write( blankRecord.Balance ); } } } 66 Create BinaryWriter and BinaryReader from FileStream Transaction.cs If the file is new, fill it with empty records

93 Get record associated with account number
// notify user of error during writing of blank records catch( IOException ) { MessageBox.Show("Cannot create file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } 73 } // end method OpenFile 75 // retrieve record depending on whether account is valid public RandomAccessRecord GetRecord( string accountValue ) { // store file data associated with account in record try { // record to store file data RandomAccessRecord record = new RandomAccessRecord(); 84 // get value from TextBox's account field int accountNumber = Int32.Parse( accountValue ); 87 // if account is invalid, do not read data if ( accountNumber < 1 || accountNumber > NUMBER_OF_RECORDS ) { // set record's account field with account number record.Account = accountNumber; } 95 // get data from file if account is valid else { // locate position in file where record exists file.Seek( ( accountNumber - 1 ) * RandomAccessRecord.SIZE, 0 ); Transaction.cs Get record associated with account number Instantiate record to hold data Find position of record

94 Store file data in record Transaction.cs
102 // read data from record record.Account = binaryInput.ReadInt32(); record.FirstName = binaryInput.ReadString(); record.LastName = binaryInput.ReadString(); record.Balance = binaryInput.ReadDouble(); } 109 return record; } 112 // notify user of error during reading catch( IOException ) { MessageBox.Show( "Cannot read file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } 119 return null; 121 } // end method GetRecord; 123 // add record to file at position determined by accountNumber public bool AddRecord( RandomAccessRecord record, int accountNumber ) { // write record to file try { // move file position pointer to appropriate position file.Seek( ( accountNumber - 1 ) * RandomAccessRecord.SIZE, 0 ); 134 Store file data in record Transaction.cs Return the record Method to insert record Use account number to determine where to enter record

95 If error occurs, notify user
// write data to file binaryOutput.Write(record.Account); binaryOutput.Write(record.FirstName); binaryOutput.Write(record.LastName); binaryOutput.Write(record.Balance); } 141 // notify user if error occurs during writing catch( IOException ) { MessageBox.Show( "Error Writing To File", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); 147 return false; // failure } 150 return true; // success 152 } // end method AddRecord 154 155 } // end class Transaction Write data to file Transaction.cs If error occurs, notify user

96 TransactionProcessor.cs 1 // Fig. 17.19: TransactionProcessor.cs
2 // MDI parent for transaction-processor application. 3 4 using System; 5 using System.Drawing; 6 using System.Collections; 7 using System.ComponentModel; 8 using System.Windows.Forms; 9 using System.Data; 10 11 public class TransactionProcessorForm : System.Windows.Forms.Form 13 { private System.ComponentModel.Container components = null; private System.Windows.Forms.MdiClient MdiClient1; 16 // reference to StartDialog private StartDialogForm startDialog; 19 // constructor public TransactionProcessorForm() { // required for Windows Form Designer support InitializeComponent(); 25 startDialog = new StartDialogForm(); startDialog.MdiParent = this; startDialog.Show(); } 30 TransactionProcessor.cs

97 TransactionProcessor.cs 31 [STAThread] 32 static void Main() 33 {
{ Application.Run( new TransactionProcessorForm() ); } 36 // Visual Studio .NET generated code 38 39 } // end class TransactionProcessorForm TransactionProcessor.cs

98 StartDialog.cs 1 // Fig. 17.20: StartDialog.cs
2 // Initial dialog box displayed to user. Provides buttons for 3 // creating/opening file and for adding, updating and removing 4 // records from file. 5 6 // C# namespaces 7 using System; 8 using System.Drawing; 9 using System.Collections; 10 using System.ComponentModel; 11 using System.Windows.Forms; 12 13 // Deitel namespaces 14 using BankLibrary; 15 16 public delegate void MyDelegate(); 17 18 public class StartDialogForm : System.Windows.Forms.Form 19 { private System.Windows.Forms.Button updateButton; private System.Windows.Forms.Button newButton; private System.Windows.Forms.Button deleteButton; private System.Windows.Forms.Button openButton; 24 private System.ComponentModel.Container components = null; 26 // reference to dialog box for adding record private NewDialogForm newDialog; 29 // reference to dialog box for updating record private UpdateDialogForm updateDialog; 32 // reference to dialog box for removing record private DeleteDialogForm deleteDialog; 35 StartDialog.cs

99 Open button clicked method
// reference to object that handles transactions private Transaction transactionProxy; 38 // Visual Studio .NET generated code 40 // invoked when user clicks New/Open File button private void openButton_Click( object sender, System.EventArgs e ) { // create dialog box enabling user to create or open file OpenFileDialog fileChooser = new OpenFileDialog(); DialogResult result; string fileName; 49 // enable user to create file if file does not exist fileChooser.Title = "Create File / Open File"; fileChooser.CheckFileExists = false; 53 // show dialog box to user result = fileChooser.ShowDialog(); 56 // exit event handler if user clicked Cancel if ( result == DialogResult.Cancel ) return; 60 // get file name from user fileName = fileChooser.FileName; 63 // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show( "Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); 68 // open or create file if user specified valid file StartDialog.cs Open button clicked method Create dialog box so user can select file Show dialog box

100 Instantiate class Transaction object
else { // create Transaction with specified file transactionProxy = new Transaction(); transactionProxy.OpenFile( fileName ); 75 // enable GUI buttons except for New/Open File button newButton.Enabled = true; updateButton.Enabled = true; deleteButton.Enabled = true; openButton.Enabled = false; 81 // instantiate dialog box for creating records newDialog = new NewDialogForm( transactionProxy, new MyDelegate( ShowStartDialog ) ); 85 // instantiate dialog box for updating records updateDialog = new UpdateDialogForm( transactionProxy, new MyDelegate( ShowStartDialog ) ); 89 // instantiate dialog box for removing records deleteDialog = new DeleteDialogForm( transactionProxy, new MyDelegate( ShowStartDialog ) ); 93 // set StartDialog as MdiParent for dialog boxes newDialog.MdiParent = this.MdiParent; updateDialog.MdiParent = this.MdiParent; deleteDialog.MdiParent = this.MdiParent; } 99 } // end method openButton_Click 101 Instantiate class Transaction object StartDialog.cs Create or open specified file Create new, update and delete child menus

101 Method to allow user to create records in the file StartDialog.cs
// invoked when user clicks New Record button private void newButton_Click( object sender, System.EventArgs e ) { Hide(); // hide StartDialog newDialog.Show(); // show NewDialog 108 } // end method newButton_Click 110 private void updateButton_Click( object sender, System.EventArgs e ) { Hide(); // hide StartDialog updateDialog.Show(); // show UpdateDialog 116 } // end method updateButton_Click 118 private void deleteButton_Click( object sender, System.EventArgs e ) { Hide(); // hide StartDialog deleteDialog.Show(); // show DeleteDialog 124 } // end method deleteButton_Click 126 protected void ShowStartDialog() { Show(); } 131 132 } // end class StartDialogForm Method to allow user to create records in the file StartDialog.cs Method to allow user to update a record Method to allow user to delete a record Displays StartDialog GUI

102 StartDialog.cs Program Output

103 UpdateDialog.cs 1 // Fig. 17.22: UpdateDialog.cs
2 // Enables user to update records in file. 3 4 // C# namespaces 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 11 // Deitel namespaces 12 using BankLibrary; 13 14 public class UpdateDialogForm : BankUIForm 15 { private System.Windows.Forms.Label transactionLabel; private System.Windows.Forms.TextBox transactionTextBox; 18 private System.Windows.Forms.Button saveButton; private System.Windows.Forms.Button cancelButton; 21 private System.ComponentModel.Container components = null; 23 // reference to object that handles transactions private Transaction transactionProxy; 26 // delegate for method that displays previous window private MyDelegate showPreviousWindow; 29 UpdateDialog.cs

104 Display record contents
// initialize components and set members to parameter values public UpdateDialogForm( Transaction transactionProxyValue, MyDelegate delegateValue ) { InitializeComponent(); showPreviousWindow = delegateValue; 37 // instantiate object that handles transactions transactionProxy = transactionProxyValue; } 41 // Visual Studio .NET generated code 43 // invoked when user enters text in account TextBox private void accountTextBox_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e ) { // determine whether user pressed Enter key if ( e.KeyCode == Keys.Enter ) { // retrieve record associated with account from file RandomAccessRecord record = transactionProxy.GetRecord( GetTextBoxValues() [ ( int )TextBoxIndices.ACCOUNT ] ); 55 // return if record does not exist if ( record == null ) return; 59 UpdateDialog.cs Display record contents Retrieve the record

105 If the record is not empty, display its contents in TextBoxes
// determine whether record is empty if ( record.Account != 0 ) { // store record values in string array string[] values = { record.Account.ToString(), record.FirstName.ToString(), record.LastName.ToString(), record.Balance.ToString() }; 69 // copy string array value to TextBox values SetTextBoxValues( values ); transactionTextBox.Text = "[Charge or Payment]"; 73 } else { // notify user if record does not exist MessageBox.Show( "Record Does Not Exist", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 83 } // end method accountTextBox_KeyDown 85 // invoked when user enters text in transaction TextBox private void transactionTextBox_KeyDown( object sender, System.Windows.Forms.KeyEventArgs e ) { // determine whether user pressed Enter key if ( e.KeyCode == Keys.Enter ) { UpdateDialog.cs If the record is not empty, display its contents in TextBoxes Add user-specified transaction to balance

106 93 // calculate balance using transaction TextBox value
try { // retrieve record associated with account from file RandomAccessRecord record = transactionProxy.GetRecord( GetTextBoxValues() [ ( int )TextBoxIndices.ACCOUNT ] ); 100 // get transaction TextBox value double transactionValue = Double.Parse( transactionTextBox.Text ); 104 // calculate new balance (old balance + transaction) double newBalance = record.Balance + transactionValue; 108 // store record values in string array string[] values = { record.Account.ToString(), record.FirstName.ToString(), record.LastName.ToString(), newBalance.ToString() }; 115 // copy string array value to TextBox values SetTextBoxValues( values ); 118 // clear transaction TextBox transactionTextBox.Text = ""; } 122 UpdateDialog.cs

107 Method to save changes the user made
// notify user if error occurs in parameter mismatch catch( FormatException ) { MessageBox.Show( "Invalid Transaction", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 131 } // end method transactionTextBox_KeyDown 133 // invoked when user clicks Save button private void saveButton_Click( object sender, System.EventArgs e ) { RandomAccessRecord record = transactionProxy.GetRecord( GetTextBoxValues() [ ( int )TextBoxIndices.ACCOUNT ] ); 141 // if record exists, update in file if ( record != null ) UpdateRecord( record ); 145 Hide(); ClearTextBoxes(); showPreviousWindow(); 149 } // end method saveButton_Click 151 UpdateDialog.cs Method to save changes the user made

108 Method to update the record
// invoked when user clicks Cancel button private void cancelButton_Click( object sender, System.EventArgs e ) { Hide(); ClearTextBoxes(); showPreviousWindow(); 159 } // end method cancelButton_Click 161 // update record in file at position specified by accountNumber public void UpdateRecord( RandomAccessRecord record ) { // store TextBox values in record and write record to file try { int accountNumber = record.Account; string[] values = GetTextBoxValues(); 170 // store values in record record.Account = accountNumber; record.FirstName = values[ ( int )TextBoxIndices.FIRST ]; record.LastName = values[ ( int )TextBoxIndices.LAST ]; record.Balance = Double.Parse( values[ ( int )TextBoxIndices.BALANCE ] ); 180 // add record to file if ( transactionProxy.AddRecord( record, accountNumber ) == false ) 184 return; // if error } UpdateDialog.cs Method to update the record Add record to file

109 UpdateDialog.cs Program Output
187 // notify user if error occurs in parameter mismatch catch( FormatException ) { MessageBox.Show( "Invalid Balance", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); 193 return; } 196 MessageBox.Show( "Record Updated", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information ); 200 } // end method UpdateRecord 202 203 } // end class UpdateDialogForm UpdateDialog.cs Program Output

110 UpdateDialog.cs Program Output

111 NewDialog.cs 1 // Fig. 17.21: NewDialog.cs
2 // Enables user to insert new record into file. 3 4 // C# namespaces 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 11 // Deitel namespaces 12 using BankLibrary; 13 14 public class NewDialogForm : BankUIForm 15 { private System.Windows.Forms.Button saveButton; private System.Windows.Forms.Button cancelButton; 18 private System.ComponentModel.Container components = null; 20 // reference to object that handles transactions private Transaction transactionProxy; 23 // delegate for method that displays previous window public MyDelegate showPreviousWindow; 26 // constructor public NewDialogForm( Transaction transactionProxyValue, MyDelegate delegateValue ) { InitializeComponent(); showPreviousWindow = delegateValue; 33 NewDialog.cs

112 Method to write record to disk
// instantiate object that handles transactions transactionProxy = transactionProxyValue; } 37 // Visual Studio .NET generated code 39 // invoked when user clicks Cancel button private void cancelButton_Click( object sender, System.EventArgs e ) { Hide(); ClearTextBoxes(); showPreviousWindow(); 47 } // end method cancelButton_Click 49 // invoked when user clicks Save As button private void saveButton_Click( object sender, System.EventArgs e ) { RandomAccessRecord record = transactionProxy.GetRecord( GetTextBoxValues() [ ( int )TextBoxIndices.ACCOUNT ] ); 57 // if record exists, add it to file if ( record != null ) InsertRecord( record ); 61 Hide(); ClearTextBoxes(); showPreviousWindow(); 65 } // end method saveButton_Click 67 NewDialog.cs Method to write record to disk Get empty record Call method to insert record

113 Method to insert record into file
// insert record in file at position specified by accountNumber private void InsertRecord( RandomAccessRecord record ) { //store TextBox values in string array string[] textBoxValues = GetTextBoxValues(); 73 // store TextBox account field int accountNumber = Int32.Parse( textBoxValues[ ( int )TextBoxIndices.ACCOUNT ] ); 77 // notify user and return if record account is not empty if ( record.Account != 0 ) { MessageBox.Show( "Record Already Exists or Invalid Number", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 84 return; } 87 // store values in record record.Account = accountNumber; record.FirstName = textBoxValues[ ( int )TextBoxIndices.FIRST]; record.LastName = textBoxValues[ ( int )TextBoxIndices.LAST]; record.Balance = Double.Parse( textBoxValues[ ( int )TextBoxIndices.BALANCE ] ); 96 // add record to file try { if ( transactionProxy.AddRecord( record, accountNumber ) == false ) Method to insert record into file NewDialog.cs If the record already exists, tell the user If location is empty, add the record

114 NewDialog.cs Program Output
102 return; // if error } 105 // notify user if error occurs in parameter mismatch catch( FormatException ) { MessageBox.Show( "Invalid Balance", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } 112 MessageBox.Show( "Record Created", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information ); 115 } // end method InsertRecord 117 118 } // end class NewDialogForm NewDialog.cs Program Output

115 NewDialog.cs Program Output

116 DeleteDialog.cs 1 // Fig. 17.23: DeleteDialog.cs
2 // Enables user to delete records in file. 3 4 // C# namespaces 5 using System; 6 using System.Drawing; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Windows.Forms; 10 11 // Deitel namespaces 12 using BankLibrary; 13 14 public class DeleteDialogForm : System.Windows.Forms.Form 15 { private System.Windows.Forms.Label accountLabel; private System.Windows.Forms.TextBox accountTextBox; 18 private System.Windows.Forms.Button deleteButton; private System.Windows.Forms.Button cancelButton; 21 private System.ComponentModel.Container components = null; 23 // reference to object that handles transactions private Transaction transactionProxy; 26 // delegate for method that displays previous window private MyDelegate showPreviousWindow; 29 // initialize components and set members to parameter values public DeleteDialogForm( Transaction transactionProxyValue, MyDelegate delegateValue) { InitializeComponent(); showPreviousWindow = delegateValue; DeleteDialog.cs

117 Method to delete a record
36 // instantiate object that handles transactions transactionProxy = transactionProxyValue; } 40 // Visual Studio .NET generated code 42 // invoked when user clicks Delete Record button private void deleteButton_Click( object sender, System.EventArgs e) { RandomAccessRecord record = transactionProxy.GetRecord( accountTextBox.Text ); 49 // if record exists, delete it in file if ( record != null ) DeleteRecord( record ); 53 this.Hide(); showPreviousWindow(); 56 } // end method deleteButton_Click 58 // invoked when user clicks Cancel button private void cancelButton_Click( object sender, System.EventArgs e) { this.Hide(); showPreviousWindow(); 65 } // end method cancelButton_Click 67 DeleteDialog.cs Method to delete a record

118 Method to delete record
// delete record in file at position specified by accountNumber public void DeleteRecord( RandomAccessRecord record ) { int accountNumber = record.Account; 72 // display error message if record does not exist if ( record.Account == 0 ) { MessageBox.Show( "Record Does Not Exist", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); accountTextBox.Clear(); 79 return; } 82 // create blank record record = new RandomAccessRecord(); 85 // write over file record with empty record if ( transactionProxy.AddRecord( record, accountNumber ) == true ) 89 // notify user of successful deletion MessageBox.Show( "Record Deleted", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information ); Method to delete record DeleteDialog.cs Test if record exists If record exists, create an empty one and overwrite existing one

119 DeleteDialog.cs Program Output
else 94 // notify user of failure MessageBox.Show( "Record could not be deleted", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); 99 accountTextBox.Clear(); 101 } // end method DeleteRecord 103 104 } // end class DeleteDialogForm DeleteDialog.cs Program Output


Download ppt "Chapter 17 – Files and Streams"

Similar presentations


Ads by Google