1 C# - Files and Streams Outline Files and Streams Classes File and Directory Creating a Sequential-Access File Reading Data from a Sequential-Access File 2 Files and Streams • 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 3 Files and Streams • System.IO.Stream: allows representation of stream as bits ▫ FileStream: read to and write from sequentialaccess and random-access files ▫ MemoryStream:transfer of data directly to and from memory ▫ BufferedStream: uses buffer to transfer to memory 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 5 // get user-specified file or directory string fileName = ??? Set fileName to what user typed // determine whether fileName is a file if ( File.Exists( fileName ) ) { See if fileName is an existing file // obtain reader and file contents try { StreamReader stream = new StreamReader( fileName ); Create string inputString = stream.ReadToEnd(); StreamReader to read text from file } // handle exception if StreamReader is unavailable Call method catch( IOException ) { } } MessageBox.Show( "File Error", "File Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); ReadToEnd 6 else { // notify user that neither file nor directory exists MessageBox.Show( filename + " does not exist", "File Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } // end if FileTest.cs If user input is not existing file output error message 7 SaveFileDialog // create dialog box enabling user to save file 8 Instantiate SaveFileDialog object SaveFileDialog fileChooser = new SaveFileDialog(); DialogResult result = fileChooser.ShowDialog(); Show SaveFileDialog // allow user to create file fileChooser.CheckFileExists = false; // exit event handler if user clicked "Cancel“ if ( result != DialogResult.Cancel ) { Test if user canceled save // get specified file name string fileName = fileChooser.FileName; // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show( "Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); Get file name to save to 9 else { // save file via FileStream if user specified valid file try Instantiate output stream { with write permission // open file with write access output = new FileStream( fileName, FileMode.OpenOrCreate, FileAccess.Write ); } // notify user if file does not exist catch ( FileNotFoundException ) { MessageBox.Show( "File Does Not Exist", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } Method to save data when user clicks enter 10 Creating or Writing to a SequentialAccess File • Programmers have to structure files to meet the requirements of applications • Declare and define a record class which describes the structure of the data • Write the main class to write out a record 11 Libraries Needed to read a file sequentially using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization; 12 [Serializable] public class Record { private int account; private string firstName; private string lastName; private double balance; Tells compiler objects of class Record can be represented as a set of bytes Data to go into record // set members to default values public Record() : this( 0, "", "", 0.0 ) { } Sets members to 0 13 // set members to parameter values public Record( int accountValue, string firstNameValue, string lastNameValue, double balanceValue ) { Account = accountValue; FirstName = firstNameValue; Set members to parameters LastName = lastNameValue; Balance = balanceValue; } // end constructor 14 // property Account public int Account { get { return account; } set Record.cs { account = value; } } // end property Account } //end class Other properties and methods 15 Main class // Creating a sequential-access file of records // C# namespaces using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization; // serializes Record in binary format private BinaryFormatter formatter = new BinaryFormatter(); // stream through which serializable data is written to file private FileStream output; 16 // Record containing TextBox values to serialize Record record = new Record(); // store values in Record and serialize Record try { record.Account = Int32.Parse( values[ ( int )TextBoxIndices.ACCOUNT ] ); record.FirstName = values[ ( int )TextBoxIndices.FIRST ]; record.LastName = values[ ( int )TextBoxIndices.LAST ]; record.Balance = Double.Parse( values[ ( int )TextBoxIndices.BALANCE ] ); Store TextBox fields in record // write Record to FileStream (serialize object) formatter.Serialize( output, record ); } Write data to file 17 // notify user if error occurs in serialization catch( SerializationException ) { MessageBox.Show( "Error Writing to File", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } Catch block if user input invalid data // notify user if error occurs regarding parameter format catch( FormatException ) { MessageBox.Show( "Invalid Format", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } Close FileStream 18 Don’t forget to close the output file! // 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(); } 19 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 // invoked when user clicks Open File button 20 User clicked open button private void openButton_Click( object sender, System.EventArgs e ) { // create dialog box enabling user to open file OpenFileDialog fileChooser = new OpenFileDialog(); Instantiate OpenFileDialog DialogResult result = fileChooser.ShowDialog(); // exit event handler if user clicked Cancel if ( result != DialogResult.Cancel ) { // get name from user fileName = fileChooser.FileName; // show error if user specified invalid file if ( fileName == "" || fileName == null ) MessageBox.Show( "Invalid File Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); Show OpenFileDialog 21 // read and display file information try { // close file from previous operation if ( input != null ) input.Close(); // create FileStream to obtain read access to file input = new FileStream( fileName, FileMode.Open, FileAccess.Read ); // traverse file until end of file while ( true ) { 22 While loop to read from file // get next Record available in file Record record = ( Record )reader.Deserialize( input ); // display record Read input from file string output = record.Account + "\t" + record.FirstName + "\t" + record.LastName + new string( ' ', 6 ) + "\t"; // display balance with correct monetary format output += String.Format( "{0:F}", balance ) + "\r\n"; // copy output to screen displayTextBox.Text += output; } 23 // handle exception when no more records catch( SerializationException ) No more records exception { // close FileStream if no Records in file input.Close(); } Close FileStream