Fall 2013 CE - 102 Computer Programming & Problem Solving CPPS
Handling Filing in C Language Chapter No 5
Files A permanent method of storing data
Records 121 Sam Jones 80 95 82 143 Jane Albright 75 92 84 etc.
File Students.txt
Files = Directory Directory = related files
Files
Collection of data under 1 name Multiple records = file File name - Max 8 characters 3 Character extension
Data Hierarchy
Byte
Field
Composed of related fields (struct)
File
Group of characters (character string “Fred”)
Record
8 bits (ASCII character ‘A’ = 01000001)
Group of related records (student record file)
Database
Group of related files (students, faculty, and staff files)
Opening a file
Create a link from file to program Equates external name to internal
Fopen()
2 arguments (1) Name for the file (2) Mode - R, W, A
Basic Filing Modes
R = read W = write A = append
Filing Modes
r
Open a file for reading
w
Open or create a file for writing If file already exists, erase the contents
Append: open or create a file Write to the end of the file
Open a file for update (reading & writing)
w+
a
r+
Open or create a file for update Erase contents of existing file
a+
Append: open or create a file for update All writing done at end of file
Writing
Creates new file Available for output Old file present - erased out_file = fopen("prices.txt","w");
Text & Binary Files
Text files
Store ASCII characters (ex: 32 = 00110011 00110010) ASCII uses only 7 bits, 8th bit is for error control Easy to read, but take up more space Examples: file.txt, file.html
Binary files
Store numbers (ex: 32 = 100000) Compact, but more complex to read Examples: file.gif, file.exe
Internal name
out_file - name used to access file File saved under prices.txt
Append
Data written to end of file
Read mode
Data available for input Can read data into program in_file=fopen("prices.txt","r"); File not found = returns null
Testing for file not found
in_file=fopen("data.txt","r"); if(in_file == null) { printf("file not there"); exit(1); }
Exit(1)
Passes control to operating system Terminates the program
Closing a file
fclose(in_file); Breaks the link to program Program termination - files automatically closed
Need to close files
Limited # can be open Closing frees up a file
More File Functions
int feof(FILE *fp)
Returns non-zero, if end-of-file Returns 0, if not end-of-file
int fclose(FILE *fp)
Closes a file Returns 0, if successful; EOF, if not Will be done automatically after a program finishes executing
Writing to a File
int fputc(int ch, FILE *fp) Writes one character to a file If successful, returns the character; if not, returns EOF int fputs(char *str, FILE *fp) Writes str to a file Returns a nonnegative value or EOF for error Does not append a \n int fprintf(FILE *fp, const char *format, arg1, arg2,… ) Same as printf function
Reading from a File
int fgetc(FILE *fp) Reads one character from a file & returns it char *fgets(char *str, int max, FILE *fp) Reads a line from a file Puts the characters (including \n) and \0 in str Max is the maximum number of characters to be written to the string int fscanf(FILE *fp, const char *format, arg1, arg2,… ) Same as scanf function
Rereading a File
Once a file is read, the file position pointer is at the end of the file File position pointer
Actually an integer value Byte location in file for next read or write Also called file offset Part of FILE structure
int rewind (FILE *fp)
Reposition to beginning of file (byte 0)
What Does This Program Do? int main(){ FILE *fp; char ch='\0'; int i = 0; if((fp = fopen("file.txt","r"))==NULL) printf("File could not be opened\n"); while((ch=fgetc(stdin))!=EOF) { while(!feof(fp)) if(ch==fgetc(fp)) i++; if(ch != '\n') printf("%d\n", i); rewind(fp); } close(fp); } return 0; }
Fputc
fputc('r',filename); Write a single character to file
else{
i=0;
Fputs
fputs(string,filename) Write a string to file
Fprintf
fprintf(filename,"format",args); fprintf(out_file,"%s%d",desc,price);
Examples
fputc('a',out_file); /* write chr */ fputs("hello",out_file); /* write string */ fprintf(out_file,"%f",val2);
Sequential vs Random access
Sequential - read from top in order Random access - Read in any order Random requires a key
File data type
FILE *infile FILE *outfile * = pointer to a file Pointer necessary as file not part of the C program
Standard file pointers
Built in to C in stdio.h FILE *stdin /* std input */ FILE *stdout /* std output */ FILE *stderr /* std error */
Stanard error
Place where error messages are sent Usually the terminal screen
Opening a file
infile = fopen("testdata", "r"); Both arguments are strings First = name as known to operating system Second = mode - r, w, a
Output
outfile = fopen("outdata","w"); outfile = fopen("outdata","a"); Append - preserves existing data If no outfile - will be created
Closing a file
Limited # of files available FOPEN_MAX has # files available Will be closed automatically by OS
Getting data from a file
fscanf(infile, "%c", &next_char); Read a character from infile Store it in next_char Like scanf - with pointer to a file
Writing to a file
fprintf(outfile, "%c", next_char); Like printf - with file pointer Store next_char in outfile
End of file
Terminates the data Written when the file is closed Can check for the end of data
Checking for end of file
int flag; flag = fscanf(infile, "%c", &next_char); while (EOF != flag)
Null pointer
If file cannot be opened Must test for this condition if(NULL == infile) printf("find the file Bozo");
File position indicator
Open to read - beginning of file fscanf - advances position indicator Go back to beginning - close - open Or rewind(infile);
Reading fgets
Read n-1 characters from file fgets(message,10,infile); Read 9 characters into message
Reading fscanf
fscanf(infile,"%f",&price); Read a floating point # Read from infile
End of file
fgetc & fscanf - return EOF fgets - returns null - \0 != EOF != NULL
Random access
fseek(infile,offset,origin); Pointer to file Offset as a long integer Where to calculate from for offset
Fseek examples
fseek(infile,4L,0); Go to 5th character in file fseek(infile,4L,1); Move ahead 5 characters
Origin values
0 - true offset - start of file 1 - Offset relative to current position 2 - Origin relative to EOF
Random-Access Files
Random-access files Individual records are fixed in length Can be accessed directly without searching though other records Much quicker to access data Use record key to find distance from beginning of file Update & delete data without overwriting other data in the file
Creating
Function fwrite() sends a block of memory to the specified file size_t fwrite(void *buffer, size_t size, size_t num, FILE *fp); buffer = start of memory size = size of each chunk of memory (in bytes) num = number of chunks of memory (in bytes) fp = the file to send the memory to Returns the number of chunks written
/*Creating a file for 100 fixed-length records*/ #include struct client{ int acctNum; char lastName[15]; char firstName[10]; double balance; }; int main() { int i; struct client blank = { 0, "", "", 0.0 }; FILE *fp; if ((fp=fopen("credit.txt","w"))==NULL) printf("File could not be opened.\n"); else { for ( i = 1; i <= 100; i++ ) fwrite(&blank,sizeof(struct client),1,fp); fclose(fp); } return 0;} //See create.c
Writing Data
Use fseek() to position the file position pointer int fseek(FILE *stream, long int offset, int whence)
stream = file pointer offset = number of bytes from “whence” whence = SEEK_SET (beginning of file) SEEK_CUR (current location) SEEK_END (end of file)
/*Writing to a file*/ FILE *fp; struct client temp = { 0, "", "", 0.0 }; if ((fp = fopen("credit.txt","r+"))==NULL) /*note: using "w" will overwrite the data*/ printf("File could not be opened.\n"); else { printf("Enter account number (1 to 100):"); scanf( "%d", &temp.acctNum ); while ( temp.acctNum != 0 ) { printf("Enter last, first & balance: "); scanf("%s%s%lf", temp.lastName, temp.firstName, &temp.balance ); fseek(fp,( temp.acctNum - 1 ) * sizeof( struct client ), SEEK_SET ); fwrite(&temp,sizeof(struct client),1,fp); printf( "Enter account number:" ); scanf( "%d", &temp.acctNum ); } fclose( fp );} //See writing.c
Reading Data
Use fread() to read a specific number of bytes from a file into memory size_t fread(void *buffer, size_t size, size_t num, FILE *fp);
buffer = start of memory size = size of each chunk of memory (in bytes) num = number of chunks of memory (in bytes) fp = the file from which the memory is read Returns the number of chunks written
/*Reading from a file*/ FILE *fp; struct client temp = { 0, "", "", 0.0 }; if((fp=fopen("credit.txt","r"))==NULL) printf("File could not be opened.\n" ); else { printf( "%-6s%-16s%-11s%10s\n", "Acct", "Last Name","First Name", "Balance" ); while(!feof(fp)){ fread(&temp,sizeof(struct client),1,fp ); if(temp.acctNum!=0) printf("%-6d%-16s%11s%10.2f\n", temp.acctNum, temp.lastName, temp.firstName, temp.balance ); } fclose(fp); } //See reading.c
Updating a Record
Ask the user for the record for updating printf("Enter account to update (1-100):"); scanf( "%d", &account ); Adjust the file position pointer & read the data into temp fseek( fp,( account - 1 ) * sizeof( struct client ), SEEK_SET ); fread( &temp, sizeof( struct client ), 1, fp );
Updating a Record
Check to see if record exists or not if ( temp.acctNum == 0 ) printf("Acount #%d has no information.\n", account ); If so, display to screen else { printf( "%-6d%-16s%-11s%10.2f\n\n", temp.acctNum, temp.lastName, temp.firstName, temp.balance );
Updating a Record
Ask user for deposit or withdrawal printf( "Enter charge ( + ) or payment ( - ): " ); scanf( "%lf", &transaction ); temp.balance += transaction; Write new data to file fseek( fp, ( account - 1 ) * sizeof( struct client ), SEEK_SET ); fwrite( &temp, sizeof( struct client ), 1, fp );
Deleting a Record
Ask the user for the record for deleting printf("Enter account to delete (1-100):"); scanf( "%d", &account ); Adjust the file position pointer & read the data into temp fseek( fp,( account - 1 ) * sizeof( struct client ), SEEK_SET ); fread( &blank, sizeof( struct client ), 1, fp );
Deleting a Record
Check to see if record exists or not if ( temp.acctNum == 0 ) printf("Acount #%d has no information.", account );
If so, delete it (write over it with empty record) else { fseek( fp, ( accountNum - 1 ) * sizeof( struct client ), SEEK_SET ); fwrite(&blank, sizeof(struct client), 1, fp ); }
File usage
Permanent data storage Back up of data Sharing data Combinig data sources Extracting pertinant data
Random access
Need a unique key for access Hash code for uniqueness Combine various elements into key Bell790gato
Network file access
Can be slow - transmission latency Faster links Replicate data Compress data
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/* Fig. 11.11: fig11_11.c Creating a randomly accessed file sequentially */ #include struct clientData { int acctNum; char lastName[ 15 ]; char firstName[ 10 ]; double balance; }; int main() { int i; struct clientData blankClient = { 0, "", "", 0.0 }; FILE *cfPtr; if ( ( cfPtr = fopen( "credit.dat", "w" ) ) == NULL ) printf( "File could not be opened.\n" ); else { for ( i = 1; i <= 100; i++ ) fwrite( &blankClient, sizeof( struct clientData ), 1, cfPtr );
1. Define struct 1.1 Initialize variable 1.2 Initialize struct 2. Open file 2.1 Write to file using unformatted output 3. Close file
fclose( cfPtr ); } return 0; }
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/* Fig. 11.12: fig11_12.c Writing to a random access file */ #include struct clientData { int acctNum; char lastName[ 15 ]; char firstName[ 10 ]; double balance; };
1. Define struct 1.1 Initialize variables 2. Open file
int main() { FILE *cfPtr; struct clientData client = { 0, "", "", 0.0 }; if ( ( cfPtr = fopen( "credit.dat", "r+" ) ) == NULL ) printf( "File could not be opened.\n" ); else { printf( "Enter account number" " ( 1 to 100, 0 to end input )\n? " ); scanf( "%d", &client.acctNum );
2.1 Input data 2.2 Write to file
while ( client.acctNum != 0 ) { printf( "Enter lastname, firstname, balance\n? " ); fscanf( stdin, "%s%s%lf", client.lastName, client.firstName, &client.balance ); fseek( cfPtr, ( client.acctNum - 1 ) * sizeof( struct clientData ), SEEK_SET ); fwrite( &client, sizeof( struct clientData ), 1, cfPtr ); printf( "Enter account number\n? " );
3. Close file 33
scanf( "%d", &client.acctNum );
34
}
35 36 37
Program Output
fclose( cfPtr ); }
38 39
return 0;
40 }
Enter account number (1 to ? 37 Enter lastname, firstname, ? Barker Doug 0.00 Enter account number ? 29 Enter lastname, firstname, ? Brown Nancy -24.54 Enter account number ? 96 Enter lastname, firstname, ? Stone Sam 34.98
100, 0 to end input) balance
balance
balance
Enter account number ? 88 Enter lastname, firstname, balance ? Smith Dave 258.34 Enter account number ? 33 Enter lastname, firstname, balance ? Dunn Stacey 314.33 Enter account number ? 0
Program Output
Reading Data Sequentially 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 argument
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/* Fig. 11.15: fig11_15.c Reading a random access file sequentially */ #include struct clientData { int acctNum; char lastName[ 15 ]; char firstName[ 10 ]; double balance; };
1. Define struct 1.1 Initialize variables 2. Read (fread)
int main() { FILE *cfPtr; struct clientData client = { 0, "", "", 0.0 };
2.1 Print
if ( ( cfPtr = fopen( "credit.dat", "r" ) ) == NULL ) printf( "File could not be opened.\n" ); else { printf( "%-6s%-16s%-11s%10s\n", "Acct", "Last Name", "First Name", "Balance" ); while ( !feof( cfPtr ) ) { fread( &client, sizeof( struct clientData ), 1, cfPtr ); if ( client.acctNum != 0 ) printf( "%-6d%-16s%-11s%10.2f\n", client.acctNum, client.lastName, client.firstName, client.balance ); }
3. Close file Program Output 33 34 35 36 37 }
Acct 29 33 37 88 96
fclose( cfPtr ); } return 0;
Last Name Brown Dunn Barker Smith Stone
First Name Nancy Stacey Doug Dave Sam
Balance -24.54 314.33 0.00 258.34 34.98
Case Study: A Transaction Processing Program
This program
We will
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
Demonstrates using random access files to achieve instant access processing of a bank’s account information Update existing accounts Add new accounts Delete accounts Store a formatted listing of all accounts in a text file
/* Fig. 11.16: fig11_16.c This program reads a random access file sequentially, updates data already written to the file, creates new data to be placed in the file, and deletes data already in the file. */ #include struct clientData { int acctNum; char lastName[ 15 ]; char firstName[ 10 ]; double balance; }; int enterChoice( void ); void textFile( FILE * ); void updateRecord( FILE * ); void newRecord( FILE * ); void deleteRecord( FILE * ); int main() { FILE *cfPtr; int choice; if ( ( cfPtr = fopen( "credit.dat", "r+" ) ) == NULL ) printf( "File could not be opened.\n" ); else { while ( ( choice = enterChoice() ) != 5 ) { switch ( choice ) {
1. Define struct 1.1 Function prototypes 1.2 Initialize variables 1.3 Link pointer and open file 2. Input choice
33 case 1: 34 textFile( cfPtr ); 35 break; 36 case 2: 37 updateRecord( cfPtr ); 38 break; 39 case 3: 40 newRecord( cfPtr ); 41 break; 42 case 4: 43 deleteRecord( cfPtr ); 44 break; 45 } 46 } 47 48 fclose( cfPtr ); 49 } 50 51 return 0; 52 } 53 54 void textFile( FILE *readPtr ) 55 { 56 FILE *writePtr; 57 struct clientData client = { 0, "", "", 0.0 }; 58 59 if ( ( writePtr = fopen( "accounts.txt", "w" ) ) == NULL ) 60 printf( "File could not be opened.\n" ); 61 else { 62 rewind( readPtr ); 63 fprintf( writePtr, "%-6s%-16s%-11s%10s\n", 64 "Acct", "Last Name", "First Name","Balance" );
65 66 while ( !feof( readPtr ) ) { 67 fread( &client, sizeof( struct clientData ), 1, 68 readPtr ); 69 70 if ( client.acctNum != 0 ) 71 fprintf( writePtr, "%-6d%-16s%-11s%10.2f\n", 72 client.acctNum, client.lastName, 73 client.firstName, client.balance ); 74 } 75 76 fclose( writePtr ); 77 } 78 79 } 80 81 void updateRecord( FILE *fPtr ) 82 { 83 int account; 84 double transaction; 85 struct clientData client = { 0, "", "", 0.0 }; 86 87 printf( "Enter account to update ( 1 - 100 ): " ); 88 scanf( "%d", &account ); 89 fseek( fPtr, 90 ( account - 1 ) * sizeof( struct clientData ), 91 SEEK_SET ); 92 fread( &client, sizeof( struct clientData ), 1, fPtr ); 93 94 if ( client.acctNum == 0 ) 95 printf( "Acount #%d has no information.\n", account ); 96 else {
2.1 Perform action 3. Close file 3.1 Function definitions
3.1 Function definitions
97 printf( "%-6d%-16s%-11s%10.2f\n\n", 98 client.acctNum, client.lastName, 99 client.firstName, client.balance ); 100 printf( "Enter charge ( + ) or payment ( - ): " ); 101 scanf( "%lf", &transaction ); 102 client.balance += transaction; 103 printf( "%-6d%-16s%-11s%10.2f\n", 104 client.acctNum, client.lastName, 105 client.firstName, client.balance ); 106 fseek( fPtr, 107 ( account - 1 ) * sizeof( struct clientData ), 108 SEEK_SET ); 109 fwrite( &client, sizeof( struct clientData ), 1, 110 fPtr ); 111 } 112 } 113 114 void deleteRecord( FILE *fPtr ) 115 { 116 struct clientData client, 117 blankClient = { 0, "", "", 0 }; 118 int accountNum; 119 120 printf( "Enter account number to " 121 "delete ( 1 - 100 ): " ); 122 scanf( "%d", &accountNum ); 123 fseek( fPtr, 124 ( accountNum - 1 ) * sizeof( struct clientData ), 125 SEEK_SET ); 126 fread( &client, sizeof( struct clientData ), 1, fPtr );
127 128 if ( client.acctNum == 0 ) 129 printf( "Account %d does not exist.\n", accountNum ); 130 else { 131 fseek( fPtr, 132 ( accountNum - 1 ) * sizeof( struct clientData ), 133 SEEK_SET ); 134 fwrite( &blankClient, 135 sizeof( struct clientData ), 1, fPtr ); 136 } 137 } 138 139 void newRecord( FILE *fPtr ) 140 { 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
struct clientData client = { 0, "", "", 0.0 }; int accountNum; printf( "Enter new account number ( 1 - 100 ): " ); scanf( "%d", &accountNum ); fseek( fPtr, ( accountNum - 1 ) * sizeof( struct clientData ), SEEK_SET ); fread( &client, sizeof( struct clientData ), 1, fPtr ); if ( client.acctNum != 0 ) printf( "Account #%d already contains information.\n", client.acctNum ); else { printf( "Enter lastname, firstname, balance\n? " ); scanf( "%s%s%lf", &client.lastName, &client.firstName, &client.balance );
3.1 Function definitions
3.1 Function definitions
157
client.acctNum = accountNum;
158
fseek( fPtr, ( client.acctNum - 1 ) *
159
sizeof( struct clientData ), SEEK_SET );
160
fwrite( &client,
161
3.1 Function definitions
sizeof( struct clientData ), 1, fPtr );
162
}
163 } 164 165 int enterChoice( void ) 166 { 167
int menuChoice;
168 169
printf( "\nEnter your choice\n"
170
"1 - store a formatted text file of acounts called\n"
171
"
172
"2 - update an account\n"
173
"3 - add a new account\n"
174
"4 - delete an account\n"
\"accounts.txt\" for printing\n"
175
"5 - end program\n? " );
176
scanf( "%d", &menuChoice );
177
return menuChoice;
178 }
After choosing option 1 accounts.txt contains: Acct 29 33 37 88 96
Last Name Brown Dunn Barker Smith Stone
First Name Nancy Stacey Doug Dave Sam
Balance -24.54 314.33 0.00 258.34 34.98
Enter account to update (1 - 100): 37 37 Barker Doug
0.00
Enter charge (+) or payment (-): +87.99 37 Barker Doug 87.99 Enter new account number (1 - 100): 22 Enter lastname, firstname, balance ? Johnston Sarah 247.45
Program Output