Home

Microsoft Visual C++/MFC File Processing: Using the C Language

     

Fundamentals of Files

 

Overview

 

A file is a series of bits of data that are arranged in a particular order to produce a usable document. For easy location and management, the bits are stored in a drive (such as a hard disc, a floppy disc, a compact disc, or any valid and supported type of storage). When these bits belong to a single but common entity, the group is referred to as a file. For even greater management, files can be stored in a parent directory or folder.

Since a file is a unit of storage and it stores information, it has a size, which is the number of bits it contains. To manage it, a file also has a location, also called a path that specifies where and/or how the file can be retrieved. Also, for better management, a file has attributes that indicate what can be done on a file or that provide specific information that the programmer or the operating system can use when dealing with the file.

There are differences and similarities between a directory and a file. Among the differences:

  • A file is used to contain data. A directory doesn't contain data
  • A directory can contain one or more files and not vice-versa
  • A directory can contain other directories
  • A file can be moved from one directory to another. This operation is not possible vice-versa since a file cannot contain a directory

The similarities of both types are:

  • A directory or a file can be created. One of the restrictions is that two files cannot have the same name inside of the same directory. Two directories cannot have the same name inside of the same parent directory
  • A directory or a file can be renamed. If a directory is renamed, the "path" of its file(s) changes
  • A directory or a file can be deleted. If a directory is deleted, its files are deleted also
  • A directory or a file can be moved. If a directory moves, it "carries" all of its files to the new location
  • A directory or a file can be copied. A file can be copied from one directory to another. If a directory is copied to a new location, all of its files are also copied to the new location

File processing consists of creating, storing, and/or retrieving the contents of a file from a recognizable medium. For example, it is used to save word-processed files to a hard drive, to store a presentation on floppy disk, or to open a file from a CD-ROM. To perform file processing on your application, you have many choices: the C and/or C++ languages, the Win32 library, or the MFC.

Characteristics of a File

In order to manage files stored in a computer, each file must be able to provide basic pieces of information about itself. This basic information is specified when the file is created but can change during the life time of a file.

To create a file, a user must first decide where it would be located: this is a requirement. A file can be located on the root drive. Alternatively, a file can be positioned inside of an existing folder. Based on security settings, a user may not be able to create a file just anywhere in the (file system of the) computer. Once the user has decided where the file would reside, there are various means of creating files that the users are trained to use.

When creating a file, the user must give it a name following the rules of the operating system combined with those of the file system.

Author Note At the time of this writing, the rules for file names were on the MSDN web site at Windows Development\Windows Base Services\Files and I/O\SDK Documentation\Storage\Storage Overview\File Management\Creating, Deleting, and Maintaining Files\Naming a File (because it is a web site and not a book, its pages can change anytime).

The most fundamental piece of information a file must have is a name. Once the user has created a file, whether the file is empty or not, the operating system assigns basic pieces of information to it. Once a file is created, it can be opened, updated, modified, renamed, etc.

Introduction to Common File Dialog Boxes

Because files on a computer can be stored in various places, Microsoft Windows provides various means of creating, locating, and managing files through objects named Windows Common Dialog Boxes. Indeed, these dialog boxes are part of the operating system and are equipped with all the necessary operations pertinent to their functionality.

The common dialog boxes available in the MFC share a parent as the CCommonDialog class. The CCommonDialog class is derived from CDialog:

CCommonDialog

The only member the CCommonDialog class has a constructor that takes a point to CWnd as argument.

C File Processing

 

Introduction

The C language provides very impressive support for file processing through a structure and many functions. The fundamental structure used to perform file processing in C is the FILE structure. In reality, to use this structure, you must call another function and get its return value.

Practical LearningPractical Learning: Introducing File Processing

  1. Start Microsoft Visual Studio
  2. To create a new application, on the main menu, click File -> New Project...
  3. In the middle list, click MFC Application
  4. Set the Name to PayrollPreparation1
  5. Click OK
  6. In the first page of the MFC Application Wizard, click Next
  7. In the second page of the wizard, click Dialog Box
  8. Click Next
  9. In the third page of the wizard, change the Dialog Title to Payroll Preparation
  10. Click Next twice
  11. Click Finish
  12. On the dialog box, click TODO: and press Delete
  13. Press the OK button and press Delete
  14. Click the Cancel button to select it
  15. In the Properties window, click Caption, type Close and press Enter
  16. Design the dialog box as follows:
     
    Payroll Preparation
    Control Caption ID Right Align Text
    Static Text Static Text Employee #:    
    Edit Control Edit Control   IDC_EMPLOYEENUMBER True
    Static Text Static Text Employee Name:    
    Edit Control Edit Control   IDC_EMPLOYEENAME  
    Static Text Static Text ________________    
    Static Text Static Text Gross Pay:    
    Edit Control Edit Control   IDC_GROSSPAY True
    Static Text Static Text Deductions    
    Static Text Static Text Federal Income Tax:    
    Edit Control Edit Control   IDC_FEDERALTAX True
    Static Text Static Text FICA Tax:    
    Edit Control Edit Control   IDC_FICATAX True
    Edit Control Edit Control   IDC_FICARATE True
    Static Text Static Text %    
    Static Text Static Text State Tax:    
    Edit Control Edit Control   IDC_STATETAX True
    Button Button Calcuate IDC_CALCULATE  
    Static Text Static Text _________________    
    Static Text Static Text Total Deductions:    
    Edit Control Edit Control   IDC_DEDUCTIONS True
    Static Text Static Text _________________    
    Static Text Static Text Net Pay:    
    Edit Control Edit Control   IDC_NETPAY True
    Static Text Static Text ===============    
    Static Text Static Text File Name:    
    Edit Control Edit Control   IDC_FILENAME  
    Button Button Open IDC_OPEN  
    Button Button Reset IDC_RESET  
    Button Button Save IDC_SAVE  
    Button Button Close IDCANCEL  
  17. Right-click each edit control, click Add Variable, select the category as Value, set the options as follows and click Finish on each:
     
    Control ID Category Variable Type Variable Name
    IDC_EMPLOYEENUMBER Value int m_EmployeeNumber
    IDC_EMPLOYEENAME Value CString m_EmployeeName
    IDC_GROSSPAY Value double m_GrossPay
    IDC_FEDERALTAX Value double m_FederalIncomeTax
    IDC_FICATAX Value CString m_FICATax
    IDC_FICARATE Value CString m_FICARate
    IDC_STATETAX Value double m_StateTax
    IDC_DEDUCTIONS Value CString m_TotalDeductions
    IDC_NETPAY Value CString m_NetPay
    IDC_FILENAME Value CString m_FileName
  18. Access the source file of the dialog box and change the initializations in the constructor as follows:
    CPayrollPreparation1Dlg::CPayrollPreparation1Dlg(CWnd* pParent /*=NULL*/)
    	: CDialogEx(CPayrollPreparation1Dlg::IDD, pParent)
    	, m_EmployeeNumber(0)
    	, m_EmployeeName(_T(""))
    	, m_GrossPay(0)
    	, m_FederalIncomeTax(0)
    	, m_FICATax(_T("0.00"))
    	, m_StateTax(0)
    	, m_FICARate(7.65)
    	, m_TotalDeductions(_T("0.00"))
    	, m_NetPay(_T("0.00"))
    	, m_FileName(_T(""))
    {
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
  19. Return to the dialog box
  20. Double-click the Calculate button
  21. Implement the event as follows:
    void CPayrollPreparation1Dlg::OnBnClickedCalculate()
    {
    	UpdateData(TRUE);
    
    	double GrossPay 	= m_GrossPay;
    	double FederalIncomeTax = m_FederalIncomeTax;
    	double FICARate		= m_FICARate;
    	double FICATax 		= m_GrossPay * FICARate / 100;
    	double StateTax 	= m_StateTax;
    	double TotalDeductions  = FederalIncomeTax + FICATax + StateTax;
    	double NetPay 		= GrossPay - TotalDeductions;
    
    	m_FICATax.Format(L"%.2f", FICATax);
    	m_TotalDeductions.Format(L"%.2f", TotalDeductions);
    	m_NetPay.Format(L"%.2f", NetPay);
    
    	UpdateData(FALSE);
    }
  22. Return to the dialog box
  23. Double-click the Reset button
  24. Implement the event as follows:
    void CPayrollPreparation1Dlg::OnBnClickedReset()
    {
    	m_EmployeeNumber   = 0;
    	m_EmployeeName     = L"";
    	m_GrossPay 	   = 0.00;
    	m_FederalIncomeTax = 0.00;
    	m_FICATax 	   = _T("0.00");
    	m_FICARate	   = 7.65;
    	m_StateTax 	   = 0.00;
    	m_TotalDeductions  = _T("0.00");
    	m_NetPay 	   = _T("0.00");
    	m_FileName 	   = L"";
    
    	UpdateData(FALSE);
    }
 
 
 

Opening a File

The primary operation of file processing consists of opening one. In the strict sense, this means that you are initiating file processing. This can be done in C by calling one of the fopen-variant functions. Their syntax are:

FILE *fopen(const char *filename, const char *mode);
FILE *_wfopen(const wchar_t *filename, const wchar_t *mode);

To support Unicode, you should use the _wfopen() version. In both cases, the first argument specifies the name of the file you want to work on. If you pass just the name of the file, the compiler will consider the directory of the current project. Otherwise, you can provide the complete path of the project. The second argument specifies the type of operation you want to perform. It is passed as a string.

When this function has been called, if it succeeds in carrying its operation (we will see what types of operations are available), it returns a FILE object. If the function fails, it returns NULL.

Creating a File

To create a file, you can pass the second argument of fopen withe one the following values:

  • "w": This specifies that you want to create a new file and write one or more values to it. If the file exists already, the compiler will replace it
  • "w+": This means that you want to create a new file to read and write one or more values to it. If the file exists already, its contents will be replaced

Writing Values to a File

The C language provides various functions you can use to write values to a file. Some functions deal with strings while others are supposed to handle any type of value. All functions that a FILE object as argument. This is the object that holds the file.

To write a character to a FILE object, you can call one of the following functions:

int fputc(int c, FILE *stream);
wint_t fputwc(wchar_t c, FILE *stream);

The first version of these functions takes a character as argument. The second takes a wide character. The character would be written to the file.

To write a string to a file, you can call one of these functions:

int fputs(const char *str, FILE *stream);
int fputws(const wchar_t *str, FILE *stream);

To write other types of values to a file, you can call one of the following functions:

size_t fwrite(const void *buffer,
	      size_t size,
   	      size_t count,
   	      FILE *stream);

To format a value before writting it to the file, you can call one  of these functions:

int fprintf(FILE *stream,
   	    const char *format [, argument ]...);
int _fprintf_l(FILE *stream,
   	       const char *format,
   	       locale_t locale [, argument ]...);
int fwprintf(FILE *stream,
   	     const wchar_t *format [, argument ]...);
int _fwprintf_l(FILE *stream,
	        const wchar_t *format,
	        locale_t locale [, argument ]...);

Closing a Stream

After using a FILE object, you should close it to free the resources it was using. This is done by calling the fclose() or _fcloseall() function. Their syntaxes are:

int fclose(FILE *stream);
int _fcloseall(void);

Practical LearningPractical Learning: Writing Values to a Stream

  1. On the dialog box, double-click the Save button
  2. Implement its event as follows:
    void CPayrollPreparation1Dlg::OnBnClickedSave()
    {
    	FILE *fstPayroll;
    	UpdateData(TRUE);
    
    	if( m_EmployeeNumber == 0 )
    	{
    		AfxMessageBox(L"You must enter an employee number.");
    		return;
    	}
    
    	if( m_EmployeeName == L"" )
    	{
    		AfxMessageBox(L"You must enter an employee name.");
    		return;
    	}
    
    	if( m_FileName == L"" )
    	{
    		AfxMessageBox(L"You must enter a name for the file.");
    		return;
    	}
    
    	fstPayroll = _wfopen(m_FileName + L".txt", L"w+");
    	
    	if( fstPayroll == NULL )
    		AfxMessageBox(L"The file was not created");
    	else
    	{
    		fwprintf(fstPayroll, L"%d\n", m_EmployeeNumber);
    		fwprintf(fstPayroll, L"%s\n", m_EmployeeName);
    		fwprintf(fstPayroll, L"%.2f\n", m_GrossPay);
    		fwprintf(fstPayroll, L"%.2f\n", m_FederalIncomeTax);
    		fwprintf(fstPayroll, L"%s\n", m_FICATax);
    		fwprintf(fstPayroll, L"%.2f\n", m_FICARate);
    		fwprintf(fstPayroll, L"%.2f\n", m_StateTax);
    		fwprintf(fstPayroll, L"%s\n", m_TotalDeductions);
    		fwprintf(fstPayroll, L"%s\n", m_NetPay);
    		
    		fclose(fstPayroll);
    	}
    
    	OnBnClickedReset();
    }
  3. Execute the application to test
  4. Enter the employee number as 281548
  5. Enter the employee name as Paul Martin Sutters
  6. In the Gross Pay, enter 428.79
  7. In the Federal Income Tax, enter 71.46
  8. In the State Tax, enter 28.86
     
    Payroll Preparation
  9. Click Calculate
  10. Enter the file name as pms
     
    Payroll Preparation
  11. Click Save
  12. Close the dialog box and return to your programming environment

Reading Values From a File

in the same way, C provides various functions to read values from a file. Like their writing counterparts, function readers take a FILE object as argument.

To read a character from a FILE object, you can call one of the following functions:

int fgetc(FILE *stream);
wint_t fgetwc(FILE *stream);

The first version reads a regular character and the second reads a wide character. To read a string from a file, you can call one of these functions:

char *fgets(char *str, int n, FILE *stream);
wchar_t *fgetws(wchar_t *str, int n, FILE *stream);

To read other types of values from a file, you can call one of the following functions:

size_t fread(void *buffer,
	     size_t size,
   	     size_t count,
   	     FILE *stream);

To read values that were formatted, you can call one  of these functions:

int fscanf(FILE *stream,
   	   const char *format [, argument ]...);
int _fscanf_l(FILE *stream,
	      const char *format,
	      locale_t locale [, argument ]...);
int fwscanf(FILE *stream,
	    const wchar_t *format [, argument ]...);
int _fwscanf_l(FILE *stream,
   	       const wchar_t *format,
   	       locale_t locale [, argument ]...);
int fscanf_s(FILE *stream,
   	     const char *format [, argument ]...);
int _fscanf_s_l(FILE *stream,
	        const char *format,
	        locale_t locale [, argument ]... );
int fwscanf_s(FILE *stream,
   	      const wchar_t *format [,
   	      argument ]...);
int _fwscanf_s_l(FILE *stream,
	         const wchar_t *format,
   		 locale_t locale [, argument ]...);

Practical LearningPractical Learning: Reading Values From a Stream

  1. On the dialog box, double-click the Open button
  2. Implement its event as follows:
    void CPayrollPreparation1Dlg::OnBnClickedOpen()
    {
    	FILE *fstPayroll;
    	wchar_t EmployeeNumber[10];
    	wchar_t EmployeeName[60];
    	wchar_t GrossPay[10];
    	wchar_t FederalIncomeTax[10];
    	wchar_t FICATax[10];
    	wchar_t FICARate[10];
    	wchar_t StateTax[10];
    	wchar_t TotalDeductions[10];
    	wchar_t NetPay[10];
    
    	UpdateData(TRUE);
    
    	if( m_FileName == L"" )
    	{
    		AfxMessageBox(L"You must enter a name for the file.");
    		return;
    	}
    
    	fstPayroll = _wfopen(m_FileName + L".txt", L"r+");
    
    	if( fstPayroll == NULL )
    		AfxMessageBox(L"The file was not opened");
    	else
    	{
    		fgetws(EmployeeNumber, 10, fstPayroll);
    		fgetws(EmployeeName, 60, fstPayroll);
    		fgetws(GrossPay, 10, fstPayroll);
    		fgetws(FederalIncomeTax, 10, fstPayroll);
    		fgetws(FICATax, 10, fstPayroll);
    		fgetws(FICARate, 10, fstPayroll);
    		fgetws(StateTax, 10, fstPayroll);
    		fgetws(TotalDeductions, 10, fstPayroll);
    		fgetws(NetPay, 10, fstPayroll);
    		
    		m_EmployeeNumber   = _wtoi(EmployeeNumber);
    		m_EmployeeName     = EmployeeName;
    		m_GrossPay		   = _wtof(GrossPay);
    		m_FederalIncomeTax = _wtof(FederalIncomeTax);
    		m_FICATax 		   = FICATax;
    		m_FICARate 		   = _wtof(FICARate);
    		m_StateTax 		   = _wtof(StateTax);
    		m_TotalDeductions  = TotalDeductions;
    		m_NetPay 		   = NetPay;
    
    		UpdateData(FALSE);
    		fclose(fstPayroll);
    	}
    }
  3. Execute the application to test it
  4. Enter the file name you had previously saved (pms)
  5. Click Open
  6. Close the dialog box and return to your programming environment
 
 
   
 

Home Copyright © 2010 FunctionX, Inc.