You are on page 1of 36

TMF 1414 INTRODUCTION

TO PROTGAMMING
LECTURE 12 – File Processing

Faculty of Computer Science and Information Technology


Objectives
• In this chapter you will learn:
– To create, read, write and update files.
– Sequential access file processing.
– Random-access file processing.

2
Introduction

3
Data Hierarchy
Data Hierarchy:
– Bit – smallest data item
• Value of 0 or 1

– Byte – 8 bits
• Used to store a character, decimal digits, letters, and special symbols

– Field – a group of characters conveying meaning


• Example: your name

– Record – group of related fields


• Represented by a struct or a class

Example: In a payroll system, a record for a particular employee that contained his/her
identification number, name, address, etc.

– File – group of related records


• Example: payroll file

– Database – a group of related files


4
Data Hierarchy

File

Record

Field

Byte (ASCII character J)

Bit 5
Data Hierarchy
• Data files
– Record key
• Identifies a record to facilitate the retrieval of
specific records from a file

– Sequential file
• Records typically sorted by key

6
Files and Streams

C views each file as a sequence of bytes


File ends with the end-of-file (EOF) marker Or, file ends at a
specified byte
Stream created when a file is opened
Provide communication channel between files and programs
Opening a file returns a pointer to a FILE structure
Example file pointers:
stdin - standard input (keyboard)
stdout - standard output (screen)
stderr - standard error (screen)
7
Files and Streams
• Read/Write functions in standard library
– fgetc
• Reads one character from a file
• Takes a FILE pointer as an argument
• fgetc (stdin) equivalent to getchar()
– fputc
• Writes one character to a file
• Takes a FILE pointer and a character to write as an argument
• fputc( 'a', stdout ) equivalent to putchar( 'a' )
– fgets
• Reads a line from a file
– fputs
• Writes a line to a file
– fscanf / fprintf
• File processing equivalents of scanf and printf
8
Creating a Sequential-Access File
• Creating a File
– FILE *cfPtr;
• Creates a FILE pointer called cfPtr

– cfPtr = fopen( "clients.dat" , "w");


• Function fopen returns a FILE pointer to file specified
• Takes two arguments – file to open and file open mode
• If open fails, NULL returned

9
Creating a Sequential-Access File
– fprintf
– Used to print to a file
– Like printf, except the first argument is a FILE pointer (pointer to the file you want to print in)
– feof ( FILE pointer )
– Returns true if end-of-file indicator (no more data to process) is set for the specified file
– fclose ( FILE pointer )
– Closes specified file
– Performed automatically when program ends
– Good practice to close files explicitly
– Details
– Programs may process no files, one file, or many files
– Each file must have a unique name and should have its own pointer

10
Create a Sequential-Access File
#include <stdio.h>

int main( void ) {


int account; /* account number */ FILE pointer definition creates
char name[ 30 ]; /* account name */ new file pointer
double balance; /* account balance */

FILE *cfPtr; /* fopen opens file. Exit program if unable to create file */

if (( cfPtr = fopen("clients.dat", "w")) == NULL ) {


printf( "File could not be opened\n" );
} /* end if */ fopen function opens a file; w
else { argument means the file is
printf( "Enter the account, name, and balance.\n");opened for writing
printf( "Enter EOF to end input.\n" );
printf( "? " );
scanf( "%d%s%lf", &account, name, &balance );
feof returns true when end of
while ( !feof( stdin ) ) {
file is reached
fprintf(cfPtr, "%d %s %.2f\n",account,name,balance);
printf("? ");
scanf("%d%s%lf", &account, name, &balance );
} /* end while */
fclose( cfPtr ); /* fclose closes file */ write account, name and balance
} /* end else */ into file with fprintf
return 0; fclose closes a file
} /*Fig. 11.3: Create a sequential file */
End-of-file (eof)
• End-of-file (Eof) key combinations for various popular operating systems.

12
File opening modes

Mode Description

r Open an existing file for reading


w Create a file for writing. If the file already exists, discard the current contents.
a Append; open or create a file for writing at the end of the file.
r+ Open an existing file for update (reading and writing).
w+ Create a file for update. If the file already exists, discard the current contents.
a+ Append: open or create a file for update; writing is done at the end of the file.
rb Open an existing file for reading in binary mode.

wb Create a file for writing in binary mode. If the file already exists, discard the current contents.

ab Append; open or create a file for writing at the end of the file in binary mode.
rb+ Open an existing file for update (reading and writing) in binary mode.
wb+ Create a file for update in binary mode. If the file already exists, discard the current contents.

ab+ Append: open or create a file for update in binary mode; writing is done at the end of the file.
13
Reading Data from a Sequential-Access File

Reading a sequential access file


– Create a FILE pointer, link it to the file to read
cfPtr = fopen( "clients.dat", "r" );

– Use fscanf to read from the file, like scanf, except first argument is a FILE pointer
fscanf( cfPtr, "%d%s%f" , &accounnt, name, &balance );

– Data read from beginning to end


rewind( cfPtr )
• Repositions file position pointer to the beginning of the file (byte 0)
– File position pointer
• Indicates the number of next byte to be read / written
• Not really a pointer, but an integer value (specifies byte location)
• Also called byte offset

14
Reading and Printing a Sequential-Access File
/*Fig.11.7: Reading and printing a sequential file */
1. #include <stdio.h>
2. int main( void ){ fopen function opens a file; r argument means
the file is opened for reading
3. int account; /* account number */
4. char name[ 30 ]; /* account name */
5. double balance; /* account balance */
6. FILE *cfPtr; /* cfPtr = clients.dat file pointer */
7.   /*fopen opens file; exits program if file cannot be opened */
8. if ( ( cfPtr = fopen( "clients.dat", "r" ) ) == NULL ) {
9. printf( "File could not be opened\n" );
10. } /* end if */
11. else { /* read account, name and balance from file */
12. printf( "%-10s%-13s%s\n", "Account", "Name", "Balance" );
13. fscanf( cfPtr, "%d%s%lf", &account, name, &balance );
14.   /*while not end of file*/ fscanf function reads a string from a file
15. while (!feof(cfPtr)){
16. printf("%-10d%-13s%7.2f\", account, name, balance);
17. fscanf(cfPtr, "%d%s%lf", &account, name, &balance);
18. } //end while
19. fclose(cfPtr); /*fclose closes the file*/
20. } /*end else*/
21. return 0;
22. } 15
Reading from Sequential-Access File
& Print Desired Data
/* Fig. 11.8: fig11_08.c -- Credit inquiry program */
1. #include <stdio.h>
2. int main( void ) {
3. int request; /* request number */
4. int account; /* account number */
5. double balance; /* account balance */
6. char name[ 30 ]; /* account name */
7. FILE *cfPtr; /* clients.dat file pointer */
8.  
9. /* fopen opens the file; exits program if file cannot be opened */
10. if ( ( cfPtr = fopen( "clients.dat", "r" ) ) == NULL ) {
11. printf( "File could not be opened\n" );
12. } /* end if */
13. else { /* display request options */
14. printf( "Enter request\n"
15. " 1 - List accounts with zero balances\n"
16. " 2 - List accounts with credit balances\n"
17. " 3 - List accounts with debit balances\n"
18. " 4 - End of run\n? " );
19. scanf( "%d", &request );
20.
21. while ( request != 4 ) { /* process user's request */
22. /* read account, name and balance from file */
23. fscanf( cfPtr, "%d%s%lf", &account, name, &balance );

cont…
16
Reading from Sequential-Access File
& Print Desired Data (cont…)
24. switch ( request ) {
25. case 1:
26. printf( "\nAccounts with zero balances:\n" );
27. /* read file contents (until eof) */
28. while ( !feof( cfPtr ) ) {
29. if ( balance == 0 ) {
30. printf( "%-10d%-13s%7.2f\n", account, name, balance );
31. } /* end if */
32.
33. /* read account, name and balance from file */
34. fscanf( cfPtr, "%d%s%lf", &account, name, &balance );
35. } /* end while */
36. break;
37. case 2:
38. printf( "\nAccounts with credit balances:\n" );
39. /* read file contents (until eof) */
40. while ( !feof( cfPtr ) ) {
41. if ( balance < 0 ) {
42. printf( "%-10d%-13s%7.2f\n", account, name, balance );
43. } /* end if */
44.
45. /* read account, name and balance from file */
46. fscanf( cfPtr, "%d%s%lf" , &account, name, &balance );

47. } /* end while */


48. break;
17
cont…
Reading from Sequential-Access File
& Print Desired Data (cont…)
49. case 3: Output:
50. printf( "\nAccounts with debit balances:\n" );
51.
52. /* read file contents (until eof) */
53. while ( !feof( cfPtr ) ) {
54. if ( balance > 0 ) {
55. printf( "%-10d%-13s%7.2f\n" , account, name, balance );
56. } /* end if */
57. /* read account, name and balance from file */
58. fscanf( cfPtr, "%d%s%lf" , &account, name, &balance );

59. } /* end while */


60. break;
61. } /* end switch */
62. rewind( cfPtr ); /* return cfPtr to beginning of file */
63. printf( "\n? " ); rewind function moves the file pointer back
64. scanf( "%d", &request ); to the beginning of the file
65. } /* end while */
66.  
67. printf( "End of run.\n" );
68. fclose( cfPtr ); /* fclose closes the file */
69. } /* end else */
70.  
71. return 0; /* indicates successful termination */
18
72. } /* end main */
Reading Data from a Sequential-Access File

• Sequential access file


– Cannot be modified without the risk of destroying other data.

– Fields can vary in size


• Different representation in files and screen than internal representation
• 1, 34, -890 are all integers but have different sizes on disk.

19
Random-Access Files
• Random access files
– Access individual records without searching through other records
– Instant access to records in a file
– Data can be inserted without destroying other data
– Data previously stored can be updated or deleted without overwriting

• Implemented using fixed-length records


– Sequential files do not have fixed length records

20
Creating a Random-Access File

• Data in random access files


– Unformatted (stored as "raw bytes")
• All data of the same type (ints, for example) uses the same amount of memory

• All records of the same type have a fixed length record

• Data not human readable

21
Creating a Random-Access File

Unformatted I/O functions


– fwrite
• Transfer bytes from a location in memory to a file
– fread
• Transfer bytes from a file to a location in memory

Example:
fwrite( &number, sizeof( int ) , 1, myPtr );
• &number – Location to transfer bytes from
• sizeof( int ) – Number of bytes to transfer
• 1 – For arrays, number of elements to transfer
» In this case, "one element" of an array is being transferred
• myPtr – File to transfer to or from

22
Creating a Random-Access File

• Writing structs
– fwrite( &myObject, sizeof (struct myStruct), 1, myPtr );
– sizeof – returns size in bytes of object in parentheses

• To write several array elements


– Pointer to array as first argument
– Number of elements to write as third argument

23
Creating a Random-Access File
1. /* Fig. 11.11: - Creating a random-access file sequentially */
2. #include <stdio.h>
3. struct clientData { /* clientData structure definition */
4. int acctNum; /* account number */
5. char lastName[ 15 ]; /* account last name */
6. char firstName[ 10 ];/* account first name */
7. double balance; /* account balance */
8. }; /* end structure clientData */ fopen function opens a file;
9. wb argument means the file is
10. int main( void ) { opened for writing in binary
11. int i; /* counter used to count from 1-100 */ mode
12. /* create clientData with default information */
13. struct clientData blankClient = { 0, "", "", 0.0};
14.
fwrite transfers bytes into a
15. FILE *CfPtr; /*credit.dat file pointer*/ random-access file
16. /* fopen opens the file; exits if file cannot be opened */
17. if ( (CfPtr = fopen( "credit.dat", "wb")) == NULL ) {
18. printf( "File could not be opened.\n" );
19. } /* end if */
20. else { /* output 100 blank records to file */
21. for ( i = 1; i <= 100; i++ ) {
22. fwrite( &blankClient, sizeof( struct clientData ), 1, CfPtr );
23. } /* end for */
24.
25. fclose ( CfPtr ); /* fclose closes the file */
26. } /* end else */
Credit.dat file with empty contents
27. return 0; /* indicates successful termination */
28. } /* end main */ 24
Writing Data Randomly to a Random-Access File

fseek
– Sets file position pointer to a specific position.
– fseek( pointer, offset, symbolic_constant );
• pointer – pointer to file
• offset – file position pointer (0 is first location)
• symbolic_constant – specifies where in file we are reading from
– SEEK_SET – seek starts at beginning of file
– SEEK_CUR – seek starts at current location in file
– SEEK_END – seek starts at end of file

25
Writing Data Randomly to a Random-Access File (Cont…)
/* Fig. 11.11: fig11_11.c - Writing to a random-access file sequentially */
1. #include <stdio.h>
2.
3. /* clientData structure definition */
4. struct clientData {
5. int acctNum; /* account number */
6. char lastName[ 15 ]; /* account last name */
7. char firstName[ 10 ]; /* account first name */
8. double balance; /* account balance */
9. }; /* end structure clientData */
10.  
11.
12. int main( void ) {
13. FILE *CfPtr; /*credit.dat file pointer*/
14.
15. /* create clientData with default information */
16.   struct clientData client = { 0, "", "", 0.0 };
17.
18. /* fopen opens the file; exits if file cannot be opened */
19. if ( (CfPtr = fopen( "credit.dat", "rb+")) == NULL ) {
20. printf( "File could not be opened.\n" );
21. } /* end if */
22. else { /* require user to specify account number */
23. printf( "Enter account number (1 - 100, 0 to end input )\n? ");
24. scanf("%d", &client.acctNum);
Cont… 26
Writing Data Randomly to a Random-Access File (Cont…)
Cont… Output:
25. /* user enters information, which is copied into file */
26. while ( client.acctNum != 0 ) {
27. /* user enters last name, first name and balance */
28. printf( "Enter lastname, firstname, balance\n? " );
29.
30. /* set record lastName, firstName and balance value */
31. fscanf(stdin,"%s%s%lf", client.lastName, client.firstName, &client.balance);
32.
33. /* seek position in file to user-specified record */
34. fseek(CfPtr, (client.acctNum - 1) * sizeof(struct clientData), SEEK_SET);
35.
Record start with 0
36. /* write user-specified information in file */
37. fwrite( &client, sizeof( struct clientData ), 1, CfPtr);
38.
39. /* enable user to input another account number */
40. printf( "Enter account number\n? " );
41. scanf( "%d", &client.acctNum );
fseek searches for a specific
42. } /* end for */
location in the random-access file
43.
44. fclose ( CfPtr ); /* fclose closes the file */
45. } /* end else */
46.
47. return 0; /* indicates successful termination */
48. } /* end main */
27
Reading Data from a Random-Access File

fread
– Reads a specified number of bytes from a file into memory

fread ( &client, sizeof(struct clientData), 1, myPtr );

– Can read several fixed-size array elements


• Provide pointer to array
• Indicate number of elements to read

– To read multiple elements, specify in third (3rd) argument

28
Reading Data from a Random-Access File
/* Fig. 11.15 - Reading a random access file sequentially */ 11. int main( void ) {
1. #include <stdio.h> 12. FILE *cfPtr; /* credit.dat file pointer */
2.   13.
3. /* clientData structure definition */ 14. /* create clientData with default information */
4. struct clientData { 15. struct clientData client = { 0, "", "", 0.0 };
5. int acctNum; /* account number */ 16.
6. char lastName[15]; /* account last name */ 17. /* fopen opens the file; exits if file cannot be opened */
7. char firstName[10]; /* account first name */ 18. if ( ( cfPtr = fopen( "credit.dat", "rb" ) ) == NULL ) {
8. double balance; /* account balance */ 19. printf( "File could not be opened.\n" );
9. }; /* end structure clientData */ 20. } /* end if */
10. 21. else {
Cont… 22. printf( "%-6s%-16s%-11s%10s\n", "Acct", "Last Name",
23. "First Name", "Balance" );
24.
fread reads bytes from a random-
25. /* read all records from file (until eof) */
access file to a location in memory
26. while ( !feof( cfPtr ) ) {
27. fread( &client, sizeof(struct clientData),1, cfPtr);
Output: 28. /* display record */
29. if ( client.acctNum != 0 ) {
30. printf( "%-6d%-16s%-11s%10.2f\n",
31. client.acctNum, client.lastName,
32. client.firstName, client.balance );
33. } /* end if */
34. } /* end while */
35. fclose( cfPtr ); /* fclose closes the file */
36. } /* end else */
37. return 0; /* indicates successful termination */
38. } /* end main */ 29
Random-Access File
( Add, Update, Delete Records)
/* Fig. 11.16: Read a random-access file sequentially, create, else { /* enable user to specify action */
update, delete record in file*/ while ( ( choice = enterChoice() ) != 5 ) {
  switch ( choice ) {
#include <stdio.h> case 1: /* create text file from record file */
#include <windows.h> textFile( cfPtr );
/* clientData structure definition */ break;
struct clientData { case 2: /* update record */
int acctNum; /* account number */ updateRecord( cfPtr );
char lastName[ 15 ]; /* account last name */ break;
char firstName[ 10 ]; /* account first name */ case 3: /* create record */
double balance; /* account balance */ newRecord( cfPtr );
}; /* end structure clientData */ break;
 
/* prototypes */ case 4: /* delete existing record */
int enterChoice( void ); deleteRecord( cfPtr );
void textFile( FILE *readPtr ); break;
void updateRecord( FILE *fPtr ); /* display message if user does not select valid choice */
void newRecord( FILE *fPtr ); default: printf( "Incorrect choice\n" );
void deleteRecord( FILE *fPtr ); break;
  } /* end switch */
int main( void ) { } /* end while */
FILE *cfPtr; /* credit.dat file pointer */ fclose( cfPtr ); /* fclose closes the file */
int choice; /* user's choice */ } /* end else */
return 0; /* indicates successful termination */
/* fopen opens the file; exits if file cannot be opened */ }
if ((cfPtr = fopen( "credit.dat", "rb+")) == NULL) {
printf( "File could not be opened.\n" ); Function main controls the Cont…
} /* end if */ operations of the program based
Cont… on user selection.
30
Random-Access File
( Add, Update, Delete Records)
/* create formatted text file for printing */ Output:
void textFile( FILE *readPtr ) {
FILE *writePtr; /* accounts.txt file pointer */

/* create clientData with default information */


struct clientData client = { 0, "", "", 0.0 };

/* fopen opens the file; exits if file cannot be opened */


if ((writePtr = fopen( "accounts.txt", "w")) == NULL) {
printf( "File could not be opened.\n" );
} /* end if */ Credit.dat
else { - Binary file
rewind( readPtr ); /* sets pointer to beginning of file */
fprintf( writePtr, "%-6s%-16s%-11s%10s\n", "Acct",
"Last Name", "First Name","Balance" );
/* copy all records from random-access file into text file */
while ( !feof( readPtr ) ) {
fread( &client, sizeof( struct clientData ), 1, readPtr );

/* write single record to text file */


if ( client.acctNum != 0 ) {
fprintf( writePtr, "%-6d%-16s%-11s%10.2f\n", Accounts.txt
client.acctNum, client.lastName, - Sequential file
client.firstName, client.balance );
} /* end if */
} /* end while */
fclose( writePtr ); /* fclose closes the file */
} /* end else */
} /* end function textFile */ Function textFile creates a text
file containing all account data
31
Random-Access File
( Add, Update, Delete Records)
/* update balance in record */ /* request transaction amount from user */
void updateRecord( FILE *fPtr ) { printf( "Enter charge ( + ) or payment ( - ): " );
int account; /* account number */ scanf( "%lf", &transaction );
double transaction; /* transaction amount */ client.balance += transaction; /* update record balance */

/* create clientData with no information */ printf( "%-6d%-16s%-11s%10.2f\n", client.acctNum,


struct clientData client = {0,"","",0.0}; client.lastName, client.firstName, client.balance);

/* obtain number of account to update */ /* move file pointer to correct record in file */
printf( "Enter account to update ( 1 - 100 ): " ); fseek(fPtr,(account-1) * sizeof(struct clientData),SEEK_SET);
scanf( "%d", &account );
/* move file pointer to correct record in file */ /* write updated record over old record in file */
fseek(fPtr,(account-1) * sizeof(struct clientData), SEEK_SET); fwrite( &client, sizeof( struct clientData ), 1, fPtr );
} /* end else */
/* read record from file */ } /* end function updateRecord */
fread( &client, sizeof( struct clientData ), 1, fPtr );

/* display error if account does not exist */ Output:


if ( client.acctNum == 0 ) {
printf( "Acount #%d has no information.\n", account );
} /* end if */
else { /* update record */
printf( "%-6d%-16s%-11s%10.2f\n\n",
client.acctNum, client.lastName,
client.firstName, client.balance );
Cont…

Function updateRecord changes the


balance of a specified account
32
Random-Access File
( Add, Update, Delete Records)
/* create and insert record */ client.acctNum = accountNum;
void newRecord( FILE *fPtr ) {
/* create clientData with default information */ /* move file pointer to correct record in file */
struct clientData client = { 0, "", "", 0.0 }; fseek(fPtr,(accountNum-1)*sizeof(struct clientData),SEEK_SET);

int accountNum; /* account number */ /* replace existing record with blank record */
fwrite( &client, sizeof( struct clientData ), 1, fPtr );
/* obtain number of account to create */ } /* end else */
printf( "Enter new account number ( 1 - 100 ): " ); } /* end function newRecord */
scanf( "%d", &accountNum );
Output:
/* move file pointer to correct record in file */
fseek(fPtr,(accountNum-1)*sizeof(struct clientData),SEEK_SET);

/* read record from file */


fread( &client, sizeof( struct clientData ), 1, fPtr );

/* display error if account already exists */


if ( client.acctNum != 0 ) {
printf( "Account #%d already contains
information.\n", client.acctNum );
} /* end if */
else { /* create record */
/* user enters last name, first name and
balance */
printf( "Enter lastname, firstname, balance\n?
" );
scanf("%s%s%lf", &client.lastName,
&client.firstName, &client.balance
Function newRecord adds );a new
account to the file Cont…
33
Random-Access File
( Add, Update, Delete Records)
/* delete an existing record */
void deleteRecord( FILE *fPtr ) {
struct clientData client; /* stores record read from file */ Output:
struct clientData blankClient = { 0, "", "", 0 }; /* blank client */

int accountNum; /* account number */

/* obtain number of account to delete */


printf( "Enter account number to delete ( 1 - 100 ): " );
scanf( "%d", &accountNum );

/* move file pointer to correct record in file */


fseek(fPtr, (accountNum-1) * sizeof(struct clientData),SEEK_SET);

/* read record from file */


fread( &client, sizeof( struct clientData ), 1, fPtr );

/* display error if record does not exist */


if ( client.acctNum == 0 ) {
printf( "Account %d does not exist.\n", accountNum );
} /* end if */
else { /* delete record */
/* move file pointer to correct record in file */
fseek(fPtr, (accountNum-1) * sizeof(struct clientData),SEEK_SET);

/* replace existing record with blank record */


fwrite( &blankClient, sizeof( struct clientData ), 1, fPtr );
} /* end else */ Function deleteRecord removes an
} /* end function deleteRecord */ existing account from the file
34
Random-Access File
( Add, Update, Delete Records)

/* enable user to input menu choice */ Output:


int enterChoice( void ) {
int menuChoice; /* variable to store user's choice */

/* display available options */


printf( "\nEnter your choice\n"
"1 - store a formatted text file of accounts called\n"
" \"accounts.txt\" for printing\n"
"2 - update an account\n"
"3 - add a new account\n"
"4 - delete an account\n"
"5 - end program\n? " );
scanf( "%d", &menuChoice ); /* receive choice from user */
return menuChoice;
} /* end function enterChoice */

Function enterChoice displays


the program menu for users to
select the operation they wish
to perform.

35
Thank You

You might also like