Home

File-Based Applications

 

The Files of a File-Based Application

 
 

Introduction

As its name indicates, a file-base application uses one or more files to hold its information. If you decide to create the application using the C# language, you can take advantage of the .NET Framework rich library and its support for file processing.

In the .NET Framework, file processing is primarily supported through the System::IO namespace that is filled with various classes to deal with files and directories (folders). The most fundamental class of the System::IO namespace and used to perform file processing is called File. The abstract and sealed File class contains all necessary methods used to create a file, check the existence of a file, write information to a file, read information from a file, or manipulate the system attributes of a file.

Another one of the fundamental file processing classes is called Stream. This is mainly an abstract class that lays a foundation for other stream-oriented classes. One of the classes that derives from Stream is called FileStream.

Creating a File

To create a new file, you can use the File class, call one of the versions of its Create() method that takes an argument as the name of, or the path to, the file and returns a FileStream object.

Besides File, you can use the StreamWriter class to create a file. To do this, declare a variable of type StreamWriter and initialize it using one of its constructors.

Writing to a File

One of the most routine operations performed on a class consists of writing information to it. And one of the most useful classes in this domain is called StreamWriter. The StreamWriter class is derived from the TextWriter class. To create a file using the StreamWriter class, you can declare a StreamWriter variable and initialize it using one of its constructors. After creating the file, you can write information to it by calling the Write() or the WriteLine() method. Always make sure you close the stream after using it. Also make sure you use exception handling in your code.

Here is an example:

File Processing

#pragma once

namespace FileBasedApplication {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace System::IO;

	. . . No Change

#pragma region Windows Form Designer generated code

	. . . No Change

#pragma endregion
	private: System::Void txtLastName_Leave(System::Object^  sender, 
		System::EventArgs^  e)
	{
	    String ^ strInitials = txtFirstName->Text->Substring(0, 1) +
                                 txtLastName->Text->Substring(0, 1);
            txtSave->Text = strInitials;
			 }
private: System::Void btnSave_Click(System::Object^  sender, System::EventArgs^  e)
	 {
            StreamWriter ^ stmWrite = gcnew StreamWriter(txtSave->Text);
            stmWrite->WriteLine(txtFirstName->Text);
            stmWrite->WriteLine(txtLastName->Text);
            stmWrite->WriteLine(dtpDateHired->Value);
            stmWrite->WriteLine(cbxGenders->Text);
            stmWrite->WriteLine(txtHourlySalary->Text);

            stmWrite->Close();

            txtFirstName->Text = L"";
            txtLastName->Text = L"";
			dtpDateHired->Value = DateTime::Today;
            cbxGenders->Text = L"Unknown";
            txtHourlySalary->Text = L"0.00";
            txtSave->Text = L"";
            txtOpen->Text = L"";
	 }
    };
}

Besides StreamWriter, to create a file and write information to it, you can use the BinaryWriter class. You start by declaring a BinaryWriter variable and initialize it using one of its constructors, passing a Stream-based object.

Practical Learning: Writing to a File

  1. Click the unit price text box that corresponds to the shirts
  2. In the Properties window, click the Events button and double-click Leave
  3. Implement the event as follows:
     
    void SaveCleaningOrder()
    {
        // We will store our files in the following folder    
        String ^ strDirectory = L"C:\\Georgetown Cleaning Services\\Receipts";
        DirectoryInfo ^ dirInfo = Directory::CreateDirectory(strDirectory);
    
        // Get the list of files, if any, from our directory
        array<FileInfo ^> ^ fleList = dirInfo->GetFiles();
    
        // If this is a new cleaning order,
        // get ready to create a name for the file
        if (IsNewCleaningOrder == true)
        {
            // If there is no file in the directory,
            // then we will use 1000 as the first file name
            if (fleList->Length == 0)
            {
                iFilename = 1000;
            }
            else // If there was at least one file in the directory
            {
                // Get a reference to the last file
                FileInfo ^ fleLast = fleList[fleList->Length - 1];
                // Get the name of the last file without its extension
    	String ^ fwe = Path::GetFileNameWithoutExtension(fleLast->FullName);
                // Increment the name of the file by 1
                iFilename = int::Parse(fwe) + 1;
            }
    
            // Update our global name of the file
            Filename = strDirectory + L"\\" + iFilename.ToString()+ L".gcs";
            txtReceiptNumber->Text = iFilename.ToString();
    
            IsNewCleaningOrder = false;
        } // If a cleaning order was already opened, we will simply update it
        else
            Filename = L"C:\\Georgetown Cleaning Services\\Receipts\\" +
    				 txtReceiptNumber->Text + L".gcs";
    
        StreamWriter ^ stmGCS = gcnew StreamWriter(Filename);
    
        try
        {
            stmGCS->WriteLine(txtCustomerName->Text);
            stmGCS->WriteLine(txtCustomerPhone->Text);
            stmGCS->WriteLine(dtpDateLeft->Value.ToString(L"D"));
            stmGCS->WriteLine(dtpTimeLeft->Value.ToString(L"t"));
            stmGCS->WriteLine(dtpDateExpected->Value.ToString(L"D"));
            stmGCS->WriteLine(dtpTimeExpected->Value.ToString(L"t"));
    
            stmGCS->WriteLine(cbxStatus->Text);
            stmGCS->WriteLine(dtpDatePickedUp->Value.ToString(L"D"));
            stmGCS->WriteLine(dtpTimePickedUp->Value.ToString(L"t"));
    
            stmGCS->WriteLine(txtUnitPriceShirts->Text);
            stmGCS->WriteLine(txtQuantityShirts->Text);
            stmGCS->WriteLine(txtSubTotalShirts->Text);
            stmGCS->WriteLine(txtUnitPricePants->Text);
            stmGCS->WriteLine(txtQuantityPants->Text);
            stmGCS->WriteLine(txtSubTotalPants->Text);
    
            stmGCS->WriteLine(cbxItem1->Text);
            stmGCS->WriteLine(txtUnitPriceItem1->Text);
            stmGCS->WriteLine(txtQuantityItem1->Text);
            stmGCS->WriteLine(txtSubTotalItem1->Text);
    
            stmGCS->WriteLine(cbxItem2->Text);
            stmGCS->WriteLine(txtUnitPriceItem2->Text);
            stmGCS->WriteLine(txtQuantityItem2->Text);
            stmGCS->WriteLine(txtSubTotalItem2->Text);
    
            stmGCS->WriteLine(cbxItem3->Text);
            stmGCS->WriteLine(txtUnitPriceItem3->Text);
            stmGCS->WriteLine(txtQuantityItem3->Text);
            stmGCS->WriteLine(txtSubTotalItem3->Text);
    
            stmGCS->WriteLine(cbxItem4->Text);
            stmGCS->WriteLine(txtUnitPriceItem4->Text);
            stmGCS->WriteLine(txtQuantityItem4->Text);
            stmGCS->WriteLine(txtSubTotalItem4->Text);
    
            stmGCS->WriteLine(txtCleaningTotal->Text);
            stmGCS->WriteLine(txtTaxRate->Text);
            stmGCS->WriteLine(txtTaxAmount->Text);
            stmGCS->WriteLine(txtNetPrice->Text);
        }
        finally
        {
            stmGCS->Close();
        }
    }
    
    System::Void txtQuantityShirts_Leave(System::Object^  sender, 
    	System::EventArgs^  e)
    {
        double unitPriceShirts = 0.00, unitPricePants = 0.00,
               unitPriceItem1 = 0.00, unitPriceItem2 = 0.00,
               unitPriceItem3 = 0.00, unitPriceItem4 = 0.00;
        double subTotalShirts = 0.00, subTotalPants = 0.00,
               subTotalItem1 = 0.00, subTotalItem2 = 0.00,
               subTotalItem3 = 0.00, subTotalItem4 = 0.00;
        int qtyShirts = 1, qtyPants = 1, qtyItem1 = 1,
            qtyItem2 = 1, qtyItem3 = 1, qtyItem4 = 4;
        double cleaningTotal = 0.00, taxRate = 0.00,
               taxAmount = 0.00, netPrice = 0.00;
    
        // Retrieve the unit price of this item
        // Just in case the user types an invalid value,
        // we are using a try...catch
        try
        {
            unitPriceShirts = double::Parse(this->txtUnitPriceShirts->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"The value you entered for the price of " 
                             L"shirts is not valid" 
                             L"\nPlease try again");
            return;
        }
    
        // Retrieve the number of this item
        // Just in case the user types an invalid value,
        // we are using a try...catch
        try
        {
            qtyShirts = int::Parse(this->txtQuantityShirts->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"The value you entered for the number of " 
                             L"shirts is not valid" 
                             L"\nPlease try again");
            return;
        }
    
        try
        {
            unitPricePants = double::Parse(this->txtUnitPricePants->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"The value you entered for the price of " 
                             L"pants is not valid" 
                             L"\nPlease try again");
            return;
        }
    
        try
        {
            qtyPants = int::Parse(this->txtQuantityPants->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"The value you entered for the number of " 
                             L"pants is not valid" 
                             L"\nPlease try again");
            return;
        }
    
        if( (cbxItem1->Text == L"None") ||
    	(cbxItem1->Text == L"") )
        {
            qtyItem1 = 0;
            unitPriceItem1 = 0.00;
        }
        else
        {
            try
            {
                unitPriceItem1 = double::Parse(this->txtUnitPriceItem1->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered for the price is not valid" 
                                 L"\nPlease try again");
                return;
            }
    
            try
            {
                qtyItem1 = int::Parse(this->txtQuantityItem1->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered is not valid" 
                                 L"\nPlease try again");
                return;
            }
        }
    
        if( (cbxItem2->Text == L"None") ||
    	(cbxItem2->Text == L"") )
        {
            qtyItem2 = 0;
            unitPriceItem2 = 0.00;
        }
        else
        {
            try
            {
                unitPriceItem2 = double::Parse(this->txtUnitPriceItem2->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered for " 
    			                 L"the price is not valid" 
                                 L"\nPlease try again");
                return;
            }
    
            try
            {
                qtyItem2 = int::Parse(this->txtQuantityItem2->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered is not valid" 
                                 L"\nPlease try again");
                return;
            }
        }
    
        if( (cbxItem3->Text == L"None") ||
    	(cbxItem3->Text == L"") )
        {
            qtyItem3 = 0;
            unitPriceItem3 = 0.00;
        }
        else
        {
            try
            {
                unitPriceItem3 = double::Parse(this->txtUnitPriceItem3->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered for the " 
    			                 L"price is not valid" 
                                 L"\nPlease try again");
                return;
            }
    
            try
            {
                qtyItem3 = int::Parse(this->txtQuantityItem3->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered is not valid" 
                                 L"\nPlease try again");
                return;
            }
        }
    
        if ((cbxItem4->Text == L"None") || (cbxItem4->Text == L""))
        {
            qtyItem4 = 0;
            unitPriceItem4 = 0.00;
        }
        else
        {
            try
            {
                unitPriceItem4 = double::Parse(this->txtUnitPriceItem4->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered for the price is not valid" 
                                 L"\nPlease try again");
                return;
            }
            try
            {
                qtyItem4 = int::Parse(this->txtQuantityItem4->Text);
            }
            catch(FormatException ^)
            {
                MessageBox::Show(L"The value you entered is not valid" 
                                 L"\nPlease try again");
                return;
            }
        }
    
        // Calculate the sub-total for this item
                subTotalShirts = qtyShirts * unitPriceShirts;
                subTotalPants = qtyPants * unitPricePants;
                subTotalItem1 = qtyItem1 * unitPriceItem1;
                subTotalItem2 = qtyItem2 * unitPriceItem2;
                subTotalItem3 = qtyItem3 * unitPriceItem3;
                subTotalItem4 = qtyItem4 * unitPriceItem4;
    
                // Calculate the total based on sub-totals
                cleaningTotal = subTotalShirts + subTotalPants + subTotalItem1 +
                        subTotalItem2 + subTotalItem3 + subTotalItem4;
    
                taxRate = double::Parse(this->txtTaxRate->Text);
                // Calculate the amount owed for the taxes
                taxAmount = cleaningTotal * taxRate / 100;
                // Add the tax amount to the total order
                netPrice = cleaningTotal + taxAmount;
    
                // Display the sub-total in the corresponding text box
                txtSubTotalShirts->Text = subTotalShirts.ToString(L"F");
                txtSubTotalPants->Text = subTotalPants.ToString(L"F");
                txtSubTotalItem1->Text = subTotalItem1.ToString(L"F");
                txtSubTotalItem2->Text = subTotalItem2.ToString(L"F");
                txtSubTotalItem3->Text = subTotalItem3.ToString(L"F");
                txtSubTotalItem4->Text = subTotalItem4.ToString(L"F");
    
                txtCleaningTotal->Text = cleaningTotal.ToString(L"F");
                txtTaxAmount->Text = taxAmount.ToString(L"F");
                txtNetPrice->Text = netPrice.ToString(L"F");
    
                SaveCleaningOrder();
    }
  4. Return to the form, click File and double-click Save
  5. Implement the event as follows:
     
    System::Void mnuFileSave_Click(System::Object^  sender, System::EventArgs^  e)
    {
        SaveCleaningOrder();
    }
  6. Return to the form
  7. Click the unit price text box that corresponds to the pants
  8. Press and hold Shift
  9. Click the unit price text boxes for item 1, item 2, item 3, and item 4
  10. Click each text box under the Qty label
  11. Click the Tax Rate text box
  12. Release Shift
  13. In the Events section of the Properties window, click Leave, click the arrow of its combo box and select txtUnitPriceShirts_Leave
  14. Execute the application
  15. Create a cleaning order
     
    Georgetown Dry Cleaner
  16. Click New and create a few more cleaning orders
     
    Georgetown Dry Cleaner
  17. Close the form and return to your programming environment
 
 
 

Reading From a File

Before exploring the contents of a file, you must first open. To open a file using the File class, you can call its Open method that is overloaded with three versions. If the information in the file is raw text, you can call the OpenText() method. After opening a file, you can read its content.

To support the ability to read from a file, you can use the StreamReader class. The StreamReader class is derived from the TextReader class. When using it, you can start by opening the file. To do this, declare a variable of type StreamReader and use one of its constructor to specify the name of, or the path to, the file. To read information from the file, you can call its Read() or its ReadLine() method. Here is an example:

System::Void btnOpen_Click(System::Object^  sender, System::EventArgs^  e)
{
    StreamReader ^ stmReader = gcnew StreamReader(txtOpen->Text);

    txtFirstName->Text = stmReader->ReadLine();
    txtLastName->Text = stmReader->ReadLine();
    dtpDateHired->Value = DateTime::Parse(stmReader->ReadLine());
    cbxGenders->Text = stmReader->ReadLine();
    txtHourlySalary->Text = stmReader->ReadLine();

    stmReader->Close();
}

System::Void btnClose_Click(System::Object^  sender, System::EventArgs^  e)
{
    Close();
}

Instead of StreamReader, you can use the BinaryReader class to read information from a file.

Practical Learning: Reading From a File

  1. On the form, click File and double-click Open
  2. Implement the event as follows:
     
    System::Void mnuFileOpen_Click(System::Object^  sender, System::EventArgs^  e)
    {
        if (txtReceiptNumber->Text == L"")
            return;
        else
        {
            try
            {
                IsNewCleaningOrder = false;
                Filename =
    		L"C:\\Georgetown Cleaning Services\\Receipts\\" +
                    txtReceiptNumber->Text+ L".gcs";
    
                StreamReader ^ rdrGCS = gcnew StreamReader(Filename);
    
                try
                {
                    txtCustomerName->Text = rdrGCS->ReadLine();
                    txtCustomerPhone->Text = rdrGCS->ReadLine();
                    dtpDateLeft->Value =
    			DateTime::Parse(rdrGCS->ReadLine());
                    dtpTimeLeft->Value =
    			DateTime::Parse(rdrGCS->ReadLine());
                    dtpDateExpected->Value =
    			DateTime::Parse(rdrGCS->ReadLine());
                    dtpTimeExpected->Value =
    			DateTime::Parse(rdrGCS->ReadLine());
    
                    cbxStatus->Text = rdrGCS->ReadLine();
                    dtpDatePickedUp->Value =
    			DateTime::Parse(rdrGCS->ReadLine());
                    dtpTimePickedUp->Value =
    			DateTime::Parse(rdrGCS->ReadLine());
    
                    txtUnitPriceShirts->Text = rdrGCS->ReadLine();
                    txtQuantityShirts->Text = rdrGCS->ReadLine();
                    txtSubTotalShirts->Text = rdrGCS->ReadLine();
                    txtUnitPricePants->Text = rdrGCS->ReadLine();
                    txtQuantityPants->Text = rdrGCS->ReadLine();
                    txtSubTotalPants->Text = rdrGCS->ReadLine();
    
                    cbxItem1->Text = rdrGCS->ReadLine();
                    txtUnitPriceItem1->Text = rdrGCS->ReadLine();
                    txtQuantityItem1->Text = rdrGCS->ReadLine();
                    txtSubTotalItem1->Text = rdrGCS->ReadLine();
    
                    cbxItem2->Text = rdrGCS->ReadLine();
                    txtUnitPriceItem2->Text = rdrGCS->ReadLine();
                    txtQuantityItem2->Text = rdrGCS->ReadLine();
                    txtSubTotalItem2->Text = rdrGCS->ReadLine();
    
                    cbxItem3->Text = rdrGCS->ReadLine();
                    txtUnitPriceItem3->Text = rdrGCS->ReadLine();
                    txtQuantityItem3->Text = rdrGCS->ReadLine();
                    txtSubTotalItem3->Text = rdrGCS->ReadLine();
    
                    cbxItem4->Text = rdrGCS->ReadLine();
                    txtUnitPriceItem4->Text = rdrGCS->ReadLine();
                    txtQuantityItem4->Text = rdrGCS->ReadLine();
                    txtSubTotalItem4->Text = rdrGCS->ReadLine();
    
                    txtCleaningTotal->Text = rdrGCS->ReadLine();
                    txtTaxRate->Text = rdrGCS->ReadLine();
                    txtTaxAmount->Text = rdrGCS->ReadLine();
                    txtNetPrice->Text = rdrGCS->ReadLine();
                }
                finally
                {
                    rdrGCS->Close();
                }
            }
            catch(FileNotFoundException ^)
            {
                MessageBox::Show(L"There is no cleaning order " 
    			    L"with that receipt number");
            }
        }
    }
  3. Execute the application
  4. Type 1001 for the receipt number and, on the main menu of the form, click File -> Open
  5. Close the form and return to your programming environment

Saving and Opening Data

We have mentioned that, on a typical database, the user is not aware of opening or saving files. In the same way, the user can be spared with deciding when to save and when not to save data. Whenever possible, most operations should be performed behind-the-scenes with little to no intervention from the user. To make this possible, you are in charge of creating the file(s), receiving data from the user, and then adding that data to the file.

Practical Learning: Opening and Saving Data

  1. Display the form
  2. In the combo box on top of the Properties window, select Form1 and click the Events button
  3. Double-click and implement the event as follows:
     
    System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
    {
        mnuFileNew_Click(sender, e);
    }
  4. Return to the form
  5. On the form, click the Customer Name text box
  6. In the Events section of the Properties window, double-click Leave and implement its event as follows:
     
    System::Void txtCustomerName_Leave(System::Object^  sender, 
    	System::EventArgs^  e)
    {
        if (txtCustomerName->Modified == true)
            SaveCleaningOrder();
    }
  7. Return to the form
  8. On the form, click the Customer Phone text box
  9. In the Events section of the Properties window, double-click Leave and implement its event as follows:
     
    System::Void txtCustomerPhone_Leave(System::Object^  sender, 
    	System::EventArgs^  e)
    {
        if (txtCustomerPhone->Modified == true)
            SaveCleaningOrder();
    }
  10. Execute the application and create a few cleaning orders
  11. Close the form and return to your programming environment
 
 
   
 

Previous Copyright © 2009-2010 FunctionX, Inc. Next