Академический Документы
Профессиональный Документы
Культура Документы
BIL 104E
INTRODUCTION TO
SCIENTIFIC AND ENGINEERING
COMPUTING
INFORMATION TO USERS
THE NOTES IN THE FOLLOWING SLIDES ARE COMPILED FROM FREE VERSIONS OF THE BOOKS Sams Teach Yourself C in 21 Days (Sams Teach Yourself) By Peter Aitken and Sams Teach Yourself C in 24 Hours (Published by Sams) By Tony Zhang.
The electronic versions of these and other books can be found in the web pages including
Introduction
Data files
Can be created, updated, and processed by C
programs Are used for permanent storage of large amounts of
data
Storage of data in variables and arrays is only temporary
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
Example: In a payroll system, a record for a particular employee that contained his/her identification number, name, address, etc.
Compiled by Ergin TARI
File
Judy Judy
Green Field
(ASCII character J)
Record
Disk Files
In former weeks, "Reading from and Writing to Standard
I/O," you learned how to read or write characters through
What Is a Stream?
The data flow you transfer from your program to a file, or vice versa, is called a stream, which is a series of bytes. Not like a file, a stream is deviceindependent. All streams have the same behavior. To perform I/O operations, you can read from or write to any type of files by simply associating a stream to the file. There are two formats of streams. The first one is called the text stream, which consists of a sequence of characters (that is, ASCII data). Depending on the compilers, each character line in a text stream may be terminated by a newline character. Text streams are used for textual data, which has a consistent appearance from one environment to another, or from one machine to another. The second format of streams is called the binary stream, which is a series of bytes. The content of an .exe file would be one example. Binary streams are primarily used for nontextual data, which is required to keep the exact contents of the file.
Compiled by Ergin TARI
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)
Filenames
Every disk file has a name, and you must use filenames when dealing with disk
files. Filenames are stored as strings, just like other text data. The rules as to what is acceptable for filenames and what is not differ from one operating system to another. In DOS and Windows 3.x, a complete filename consists of a name that has from one to eight characters, optionally followed by a period and an extension that has from one to three characters. In contrast, the Windows 95 and Windows NT operating systems, as well as most UNIX systems, permit filenames up to 256 characters long. Operating systems also differ in the characters that are permitted in filenames. In Windows 95, for example, the following characters are not permitted: /\:*?"<>| You must be aware of the filename rules of whichever operating system you're writing for.
Compiled by Ergin TARI
Filenames
A filename in a C program also can contain path information. The path specifies the drive and/or directory (or folder) where the file is located. If you specify a filename without a path, it will be assumed that the file is located at whatever location the operating system currently designates as the default. It's good programming practice to always specify path information as part of your filenames. On PCs, the backslash character is used to separate directory names in a path. For example, to DOS and Windows, the name You are strictly required to do if use windows z:\data\list.txt refers to a file named LIST.TXT in the directory \DATA on drive Z. Remember that the backslash character has a special meaning to C when it's in a string. To represent the backslash character itself, you must precede it with another backslash. Thus, in a C program, you would represent the filename as follows: char *filename = z:\\data\\list.txt"; If you're entering a filename using the keyboard, however, enter only a single backslash.
Not all systems use the backslash as the directory separator. For example, UNIX uses the forward slash (/).
FILE *fptr;
#include <stdio.h>
Here filename is a char pointer that references a string of a filename. The filename is given to the file that is about to be opened by the fopen() function. mode points to another string that specifies the way to open the file. The fopen() function returns a pointer of type FILE. If an error occurs during the procedure to open a file, the fopen() function returns a null pointer.
Note that you might see people use the mode "rb+" instead of "r+b". These two strings are equivalent. Similarly, "wb+" is the same as "w+b"; "ab+" is equivalent to "a+b".
Compiled by Ergin TARI
Here "r" is used to indicate that a text file is about to be opened for
reading only. If an error occurs when the fopen() function tries to open the file, the function returns a null pointer. Then an error message is
Here stream is a file pointer that is associated with a stream to the opened file. If fclose() closes a file successfully, it returns 0. Otherwise, the function returns EOF. Normally, the fclose() function fails only when the disk is removed before the function is called or there is no more space left on the disk.
Compiled by Ergin TARI
Output
The value of fptr: 0x013E Ready to close the file.
ANALYSIS
From the expression in line 12, you can see that the fopen() function tries to open a text file with the name contained by the character array filename for reading. The filename array is defined and initialized with the name haiku.txt in line 9. If an error occurs when you try to open the text file, the fopen() function returns a null pointer. Line 13 then prints a warning message, and line 14 assigns the value represented by the enum name FAIL to the int variable reval. From the declaration of the enum data type in line 4, we know that the value of FAIL is 1. If, however, the fopen() function opens the text file successfully, the statement in line 16 prints the value contained by the file pointer fptr. Line 17 tells the user that the program is about to close the file, and line 18 then closes the file by calling the fclose() file. In line 21, the return statement returns the value of reval that contains 0 if the text file has been opened successfully, or 1 otherwise. From the output shown on my screen, I see that the value held by the file pointer fptr is 0x013E after the text file is opened.
Compiled by Ergin TARI
feof() function
In C, a function called feof() can be used to determine when the end of a file is encountered. This function is more useful when you're reading a binary file because the values of some bytes may be equal to the value of EOF. If you determine the end of a binary file by checking the value returned by fread(), you may end up at the wrong position. Using the feof() function helps you to avoid mistakes in determining the end of a file.
The syntax for the feof() function is #include <stdio.h> int feof(FILE *stream);
Here stream is the file pointer that is associated with an opened file. The feof() function returns 0 if the end of the file has not been reached; otherwise, it returns a nonzero integer.
Compiled by Ergin TARI
Lecture 11, Page 22 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: 33: /* Detecting end-of-file. */ #include <stdlib.h> #include <stdio.h> #define BUFSIZE 100 main() { char buf[BUFSIZE]; char filename[60]; FILE *fp;
Enter name of text file to display: hello.c #include <stdio.h> main() { printf("Hello, world."); return(0); }
puts("Enter name of text file to display: "); gets(filename); /* Open the file for reading. */ if ( (fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "Error opening file."); exit(1); } /* If end of file not reached, read a line and display it. */
1: /* Demonstrates the fprintf() function. */ 2: #include <stdlib.h> 3: #include <stdio.h> 4: Enter 5 floating-point numerical 5: void clear_kb(void); 6: 3.14159 7: main() 9.99 8: { 9: FILE *fp; 1.50 10: float data[5]; 3. 11: int count; 1000.0001 12: char filename[20]; 13: Enter a name for the file. 14: puts("Enter 5 floating-point numerical values."); numbers.txt 15: 16: for (count = 0; count < 5; count++) 17: scanf("%f", &data[count]); 18: 19: /* Get the filename and open the file. First clear stdin */ 20: /* of any extra characters. */ 21: 22: clear_kb(); 23: 24: puts("Enter a name for the file."); 25: gets(filename); 26: 27: if ( (fp = fopen(filename, "w")) == NULL) 28: { 29: fprintf(stderr, "Error opening file %s.", filename); 30: exit(1); 31: } 32: 33:
values.
/* Write the numerical data to the file and to stdout. */ 34: 35: for (count = 0; count < 5; count++) 36: { 37: fprintf(fp, "\ndata[%d] = %f", count, data[count]); 38: fprintf(stdout, "\ndata[%d] = %f", count, data[count]); 39: } 40: fclose(fp); 41: printf("\n"); 42: return(0); 43: } Enter 5 floating-point numerical values. 44: 3.14159 45: void clear_kb(void) 46: /* Clears stdin of any waiting characters. */ 9.99 47: { 1.50 48: char junk[80]; 3. 49: gets(junk); 1000.0001 50: }
Enter a name for the file. numbers.txt data[0] = 3.141590 data[1] = 9.990000 data[2] = 1.500000 data[3] = 3.000000 data[4] = 1000.000122
Lecture 11, Page 27 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: /* Reading formatted file data with fscanf(). */ #include <stdlib.h> #include <stdio.h> main() { float f1, f2, f3, f4, f5; FILE *fp;
if ( (fp = fopen("INPUT.TXT", "r")) == NULL) { fprintf(stderr, "Error opening file.\n"); exit(1); } fscanf(fp, "%f %f %f %f %f", &f1, &f2, &f3, &f4, &f5); printf("The values are %f, %f, %f, %f, and %f\n.", f1, f2, f3, f4, f5); fclose(fp); return(0); }
Read or write one character at a time. Read or write one line of text (that is, one character line) at a time. Read or write one block of characters at a time.
Here stream is the file pointer that is associated with a stream. The fgetc() function fetches the next character from the stream specified by stream. The function then returns the value of an int that is converted from the character. The syntax for the fputc() function is
#include <stdio.h> int fputc(int c , FILE *stream);
Here c is an int value that represents a character. In fact, the int value is converted to an unsigned char before being outputted. stream is the file pointer that is associated with a stream. The fputc() function returns the character written if the function is successful; otherwise, it returns EOF. After a character is written, the fputc() function advances the associated file pointer.
Compiled by Ergin TARI
Leading me along my shadow goes back home from looking at the moon. --- Sodo (1641-1716)
A storm wind blows out from among the grasses the full moon grows. --- Chora (1729-1781)
Compiled by Ergin TARI
Output
Analysis
The purpose of the program is to read one character from a file, write the character to another file, and then display the character on the screen. (You need to copy or create the file, haiku.txt, from the book, and put it in the same directory where you save the executable file. haiku.txt is the text file that is going to be read by the program.) In the program there is a function called CharReadWrite(), which has two file pointers as its arguments. (See the declaration of the CharReadWrite() function in line 6.) The statement in line 10 defines two file pointers, fptr1 and fptr2, which are used later in the program. Lines 11 and 12 define two character arrays, filename1 and filename2, and initialize the two arrays with two strings containing filenames, outhaiku.txt and haiku.txt. In line 15, a text file with the name outhaiku.txt is opened for writing. outhaiku.txt is contained by the filename1 array. The file pointer fptr1 is associated with the file. If the fopen() function returns NULL, which means an error occurs, a warning message is printed out in line 16. Also, in line 17, the reval variable is assigned 1 and is represented by the enum name FAIL. If the file outhaiku.txt is opened successfully, another text file, called haiku.txt, is opened for reading in line 18. The file pointer fptr2 is associated with the opened text file.
Compiled by Ergin TARI
Analysis
If no error occurs, the CharReadWrite() function is invoked in line 22 with two file pointers, fptr1 and fptr2, passed to the function as arguments. From the definition of the CharReadWrite() function in lines 30 and 38, we see that there is a while loop that keeps calling the fgetc() function to read the next character from the haiku.txt text file until the function reaches the end of the file. (See line 34.) Within the while loop, the fputc() function in line 35 writes each character read from the haiku.txt file to another text file, outhaiku.txt, which is pointed to by fout. In addition, putchar() is called in line 36 in order to put the character returned by the fgetc() function on the screen. After the CharReadWrite() function finishes its job, the two opened files, which are associated with fptr1 and fptr2, are closed with a call to the fclose() function respectively in lines 23 and 24. As mentioned earlier, the haiku.txt file contains two pieces of Japanese haiku written by Sodo and Chora. If the program in Listing 21.2 is run successfully, we see the two pieces of haiku shown on the screen, and they are written into the outhaiku.txt file as well. You can view outhaiku.txt in a text editor to confirm that the content of haiku.txt has been correctly copied to outhaiku.txt.
Here s references a character array that is used to store characters read from the opened file pointed to by the file pointer stream. n specifies the maximum number of array elements. If it is successful, the fgets() function returns the char pointer s. If EOF is encountered, the fgets() function returns a null pointer and leaves the array untouched. If an error occurs, the function returns a null pointer, and the contents of the array are unknown. The fgets() function can read up to n-1 characters, and can append a null character after the last character fetched, until a newline or an EOF is encountered. Note that if a newline is encountered during the reading, the fgets() function includes the newline in the array. This is different from what the gets() function does. The gets() function just replaces the newline character with a null character.
Compiled by Ergin TARI
Here s points to the array that contains the characters to be written to a file associated with the file pointer stream. The const modifier indicates that the content of the array pointed to by s cannot be changed. If it fails, the fputs() function returns a nonzero value; otherwise, it returns zero. Note that the character array must include a null character at the end as the terminator to the fputs() function. Also, unlike the puts() function, the fputs() function does not insert a newline character to the string written to a file. We can modify the previous program to read or write one character line at a time by calling the fgets() and fputs() functions. The modified version is shown in te next slide.
Compiled by Ergin TARI
1: /* Reading and writing one line at a time */ 29: /* function definition */ 2: #include <stdio.h> 30: void LineReadWrite(FILE *fin, FILE *fout) 4: enum {SUCCESS, FAIL, MAX_LEN = 81}; 31: { 5: 32: char buff[MAX_LEN]; 6: void LineReadWrite(FILE *fin, FILE *fout); 33: 7: 34: while (fgets(buff, MAX_LEN, fin) != NULL){ 8: main(void) 35: fputs(buff, fout); 9: { 36: printf("%s", buff); 10: FILE *fptr1, *fptr2; 37: } 11: char filename1[]= "outhaiku.txt"; 38: } 12: char filename2[]= "haiku.txt"; 13: int reval = SUCCESS; Leading me along 14: my shadow goes back home 15: if ((fptr1 = fopen(filename1, "w")) == NULL){ 16: printf("Cannot open %s for writing.\n", filename1); from looking at the moon. 17: reval = FAIL; --- Sodo 18: } else if ((fptr2 = fopen(filename2, "r")) == NULL){ (1641-1716) 19: printf("Cannot open %s for reading.\n", filename2); 20: reval = FAIL; A storm wind blows 21: } else { out from among the grasses 22: LineReadWrite(fptr2, fptr1); 23: fclose(fptr1); the full moon grows. 24: fclose(fptr2); --- Chora 25: } (1729-1781) Compiled by Ergin TARI 27: return reval;}
Output
Analysis
From the program, you can see that a function called LineReadWrite() has replaced the CharReadWrite() function. The definition of the LineReadWrite() function is shown in lines 30_38. The fgets() function is called repeatedly in a while loop to read one character line at a time from the haiku.txt text file, until it reaches the end of the text file. In line 34, the array name buff and the maximum number of the array elements MAX_LEN are passed to the fgets() function, along with the file pointer fin that is associated with the opened haiku.txt file. Meanwhile, each line read by the fgets() function is written to another opened text file called outhaiku.txt that is associated with the file pointer fout. This is done by invoking the fputs() function in line 35. The statement in line 36 prints the contents of each string on the screen so that you see the two pieces of Japanese verse after running the program. Also, you can view the outhaiku.txt file in a text editor to make sure that the contents of the haiku.txt file have been copied to the outhaiku.txt file.
Compiled by Ergin TARI
The number of elements read by the fread() function should be equal to the value specified by the third argument to the function, unless an error occurs or an EOF (endof-file) is encountered. The fread() function returns the number of elements that are actually read, if an error occurs or an EOF is encountered.
Compiled by Ergin TARI
1: /* Direct file I/O with fwrite() and fread(). */ 2: #include <stdlib.h> 3: #include <stdio.h> 5: #define SIZE 20 6: 7: main() 8: { 9: int count, array1[SIZE], array2[SIZE]; 10: FILE *fp; 11: 12: /* Initialize array1[]. */ 13: 14: for (count = 0; count < SIZE; count++) 15: array1[count] = 2 * count; 16: 17: /* Open a binary mode file. */ 18: 19: if ( (fp = fopen("direct.txt", "wb")) == NULL) 20: { 21: fprintf(stderr, "Error opening file."); 22: exit(1); 23: } 24: /* Save array1[] to the file. */ 25: 26: if (fwrite(array1, sizeof(int), SIZE, fp) != SIZE) 27: { 28: fprintf(stderr, "Error writing to file."); 29: exit(1); 30: } 32: fclose(fp); 33:
34: /* Now open the same file for reading in binary mode. */ 35: 36: if ( (fp = fopen("direct.txt", "rb")) == NULL) 37: { 38: fprintf(stderr, "Error opening file."); 39: exit(1); 40: } 41: 42: /* Read the data into array2[]. */ 43: 44: if (fread(array2, sizeof(int), SIZE, fp) != SIZE) 45: { 46: fprintf(stderr, "Error reading file."); 47: exit(1); 48: } 49: 50: fclose(fp); 51: 52: /* Now display both arrays to show they're the same. */ 53: 54: for (count = 0; count < SIZE; count++) 55: printf("%d\t%d\n", array1[count], array2[count]); 56: return(0); 57: }
0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
Analysis
The purpose of the program is to show you how to invoke the fread() and fwrite() functions in your program to perform block I/O operations. In the program, the haiku.txt file is read by the fread() function, and then the fwrite() function is used to write the contents read from haiku.txt to another file called outhaiku.txt. We call the two C I/O functions from our own function, BlockReadWrite(). From the definition of the BlockReadWrite() function in lines 29_40, you can see that a character array called buff is defined with the number of elements of MAX_LEN + 1 in line 32, although we only read MAX_LEN number of characters by calling the fread() function in line 35. The reason is that we append a null character in line 36 after the last character read so that we ensure the block of characters saved in buff is treated as a string and can be printed out on the screen properly by the printf() function in line 37. The while loop, shown in lines 34_39, keeps calling the fread() function to read a character block with MAX_LEN elements, until the feof() function in line 34 returns 0, which means that the end of the text file has been reached. As shown in lines 35 and 38, we use the sizof operator to measure the size of the char data type because the elements in the buff array are all characters.
Compiled by Ergin TARI
int fcloseall(void);
This function also flushes any stream buffers and returns the number of streams closed. When a program terminates (either by reaching the end of main() or by executing the exit() function), all streams are automatically flushed and closed. However, it's a good idea to close streams explicitly--particularly those linked to disk files--as soon as you're finished with them. The reason has to do with stream buffers. When you create a stream linked to a disk file, a buffer is automatically created and associated with the stream. A buffer is a block of memory used for temporary storage of data being written to and read from the file. Buffers are needed because disk drives are block-oriented devices, which means that they operate most efficiently when data is read and written in blocks of a certain size. The size of the ideal block differs, depending on the specific hardware in use. It's typically on the order of a few hundred to a thousand bytes. You don't need to be concerned about the exact block size, however.
Compiled by Ergin TARI
beginning of the file if the file was opened in any other mode.
The file input/output functions covered earlier make use of the position indicator, although the manipulations go on behind the scenes. Writing and reading operations occur at the location of the position indicator and update the position indicator as well. For example, if you open a file for reading, and 10 bytes are read, you input the first 10 bytes in the file (the bytes at positions 0 through 9). After the read operation, the position indicator is at position 10, and the next read operation begins there. Thus, if you want to read all the data in a file sequentially or write data to a file sequentially, you don't need to be concerned about the position indicator, because the stream I/O functions take care of it automatically. When you need more control, use the C library functions that let you determine and change the value of the file position indicator. By controlling the position indicator, you can perform random file access. Here, random means that you can read data from, or write data to, any position in a file without reading or writing all the preceding data.
To determine the value of a file's position indicator, use ftell(). This function's prototype,
located in STDIO.H, reads long ftell(FILE *fp); The argument fp is the FILE pointer returned by fopen() when the file was opened. The function ftell() returns a type long that gives the current file position in bytes from the start of the file (the first byte is at position 0). If an error occurs, ftell() returns -1L (a type long -1).
1: /* Demonstrates ftell() and rewind(). */ 2: #include <stdlib.h> 3: #include <stdio.h> 4: 5: #define BUFLEN 6 6: 7: char msg[] = "abcdefghijklmnopqrstuvwxyz"; 8: 9: main() 10: { 11: FILE *fp; 12: char buf[BUFLEN]; 13: 14: if ( (fp = fopen("TEXT.TXT", "w")) == NULL) 15: { 16: fprintf(stderr, "Error opening file."); 17: exit(1); 18: } 19: 20: if (fputs(msg, fp) == EOF) 21: { 22: fprintf(stderr, "Error writing to file."); 23: exit(1); 24: } 25: 26: fclose(fp); 27:
Immediately after opening, position = 0 After reading in abcde, position = 5 The next 5 characters are fghij, and position now = 10 After rewinding, the position is back at 0 and reading starts at the beginning again: abcde
Lecture 11, Page 47 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: } /* Now open the file for reading. */
if ( (fp = fopen("TEXT.TXT", "r")) == NULL) { fprintf(stderr, "Error opening file."); exit(1); } printf("\nImmediately after opening, position = %ld", ftell(fp)); /* Read in 5 characters. */
fgets(buf, BUFLEN, fp); printf("\nAfter reading in %s, position = %ld", buf, ftell(fp)); /* Read in the next 5 characters. */
fgets(buf, BUFLEN, fp); printf("\n\nThe next 5 characters are %s, and position now = %ld", buf, ftell(fp));
/* Rewind the stream. */ rewind(fp); printf("\n\nAfter rewinding, the position is back at %ld", ftell(fp)); /* Read in 5 characters. */ fgets(buf, BUFLEN, fp); printf("\nand reading starts at the beginning again: %s\n", buf); fclose(fp); return(0);
Compiled by Ergin TARI
Constant SEEK_SET
Value 0
Description Moves the indicator offset bytes from the beginning of the file.
SEEK_CUR
SEEK_END
1
2
The function fseek() returns 0 if the indicator was successfully moved or nonzero if an error occurred.
Compiled by Ergin TARI
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: 33: 34:
35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: }
fclose(fp); /* Open the file for reading. */ if ( (fp = fopen("RANDOM.DAT", "rb")) == NULL) { fprintf(stderr, "\nError opening file."); exit(1); }
/* Ask user which element to read. Input the element */ /* and display it, quitting when -1 is entered. */
while (1) { printf("\nEnter element to read, 0-%d, -1 to quit: ",MAX-1); scanf("%ld", &offset); if (offset < 0) break; else if (offset > MAX-1) continue; /* Move the position indicator to the specified element. */ if ( (fseek(fp, (offset*sizeof(int)), SEEK_SET)) != 0) { fprintf(stderr, "\nError using fseek()."); exit(1); } /* Read in a single integer. */ fread(&data, sizeof(int), 1, fp); } printf("\nElement %ld has value %d.", offset, data);
Lecture 11, Enter element to read, 0-49, -1 to quit: 5 Page 50 Element 5 has value 50. Enter element to read, 0-49, -1 to quit: 6 Element 6 has value 60. Enter element to read, 0-49, -1 to quit: 49 Element 49 has value 490. Enter element to read, 0-49, -1 to quit: 1 Element 1 has value 10. Enter element to read, 0-49, -1 to quit: 0 Element 0 has value 0. Enter element to read, 0-49, -1 to quit: -1
fclose(fp); return(0);
Compiled by Ergin TARI
Deleting a File
To delete a file, you use the library function remove(). Its prototype is in STDIO.H,
as follows:
int remove( const char *filename ); The variable *filename is a pointer to the name of the file to be deleted. (See the
section on filenames earlier in this week.) The specified file must not be open. If the
file exists, it is deleted (just as if you used the DEL command from the DOS prompt or the rm command in UNIX), and remove() returns 0. If the file doesn't exist, if it's read-only, if you don't have sufficient access rights, or if some other error occurs, remove() returns -1.
/* Demonstrates the remove() function. */ #include <stdio.h> main() { char filename[80]; printf("Enter the filename to delete: "); gets(filename); if ( remove(filename) == 0) printf("The file %s has been deleted.\n", filename); else fprintf(stderr, "Error deleting the file %s.\n", filename); return(0); }
Enter the filename to delete: *.bak Error deleting the file *.bak. Enter the filename to delete: list1414.bak The file list1414.bak has been deleted.
Renaming a File
The rename() function changes the name of an existing disk file. The function prototype, in STDIO.H, is as follows: int rename( const char *oldname, const char *newname );
The filenames pointed to by oldname and newname follow the rules given earlier
in this chapter. The only restriction is that both names must refer to the same disk drive; you can't rename a file to a different disk drive. The function rename() returns 0 on success, or -1 if an error occurs. Errors can be caused by the following conditions (among others): The file oldname does not exist. A file with the name newname already exists. You try to rename to another disk.
: /* Using rename() to change a filename. */ 2: 3: #include <stdio.h> 4: 5: main() 6: { 7: char oldname[80], newname[80]; Enter current filename: list1609.c 8: Enter new name for file: rename.c 9: printf("Enter current filename: "); list1609.c has been renamed rename.c. 10: gets(oldname); 11: printf("Enter new name for file: "); 12: gets(newname); 13: 14: if ( rename( oldname, newname ) == 0 ) 15: printf("%s has been renamed %s.\n", oldname, newname); 16: else 17: fprintf(stderr, "An error has occurred renaming %s.\n", oldname); 18: return(0); 19: }
Copying a File
It's frequently necessary to make a copy of a file--an exact duplicate with a different name (or with the same name but in a different drive or directory). In DOS, you do this with the COPY command, and other operating systems have equivalents. How do you copy a file in C? There's no library function, so you need to write your own. This might sound a bit complicated, but it's really quite simple thanks to C's use of streams for input and output. Here are the steps you follow:
1. Open the source file for reading in binary mode. (Using binary mode ensures that the function can copy all sorts of files, not just text files.)
4. If the function feof() indicates that you've reached the end of the source file, you're done and can close both files and return to the calling program.
5. If you haven't reached end-of-file, write the character to the destination file, and then loop back to step 3.
1: /* Copying a file. */ 2: 3: #include <stdio.h> 4: 5: int file_copy( char *oldname, char *newname ); 6: 7: main() 8: { 9: char source[80], destination[80]; 10: 11: /* Get the source and destination names. */ 12: 13: printf("\nEnter source file: "); 14: gets(source); 15: printf("\nEnter destination file: "); 16: gets(destination); 17: 18: if ( file_copy( source, destination ) == 0 ) 19: puts("Copy operation successful"); 20: else 21: fprintf(stderr, "Error during copy operation"); 22: return(0); 23: } 24: int file_copy( char *oldname, char *newname ) 25: { 26: FILE *fold, *fnew; 27: int c; 28: 29: /* Open the source file for reading in binary mode. */ 30: 31: if ( ( fold = fopen( oldname, "rb" ) ) == NULL ) 32: return -1; 33:
34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: }
if ( ( fnew = fopen( newname, "wb" ) ) == NULL ) { fclose ( fold ); return -1; } /* Read one byte at a time from the source; if end of file */ /* has not been reached, write the byte to the */ /* destination. */
while (1) { c = fgetc( fold ); if ( !feof( fold ) ) fputc( c, fnew ); else break; } fclose ( fnew ); fclose ( fold ); return 0;
Enter source file: list1610.c Enter destination file: tmpfile.c Copy operation successful
Compiled by Ergin TARI
temporary file is a file that is created by the program, used for some purpose during
program execution, and then deleted before the program terminates. When you create a temporary file, you don't really care what its name is, because it gets
deleted. All that is necessary is that you use a name that isn't already in use for
another file. The C standard library includes a function tmpnam() that creates a valid filename that doesn't conflict with any existing file. Its prototype in STDIO.H is as follows: char *tmpnam(char *s); The arguments must be a pointer to a buffer large enough to hold the filename. You can also pass a null pointer (NULL), in which case the temporary name is stored in a buffer internal to tmpnam(), and the function returns a pointer to that buffer.
1: /* Demonstration of temporary filenames. */ 2: 3: #include <stdio.h> 4: 5: main() 6: { 7: char buffer[10], *c; 8: 9: /* Get a temporary name in the defined buffer. */ 10: 11: tmpnam(buffer); 12: 13: /* Get another name, this time in the function's */ 14: /* internal buffer. */ 15: 16: c = tmpnam(NULL); 17: 18: /* Display the names. */ 19: 20: printf("Temporary name 1: %s", buffer); 21: printf("\nTemporary name 2: %s\n", c); 22: }
Summary
In C, a file can refer to a disk file, a terminal, a printer, or a tape drive. The data flow you transfer from your program to a file, or vice versa, is called a stream. A stream is a series of ordered bytes. Not like a file, a stream is device-independent. There are two stream formats: text stream and binary stream. The file position indicator in the FILE structure points to the position in a file where data will be read from or written to. The fopen() function is used to open a file and associate a stream to the opened file. You can specify different modes for opening a file. The fclose() function is responsible for closing an opened file and disassociating a stream with the file. The fgetc() and fputc() functions read or write one character at a time. The fgets() and fputs() functions read or write one line at a time. The fread() and fwrite() functions read or write one block of data at a time. The feof() function can determine when the end of a file has been reached. In a binary file, the feof() function should be used to detect EOF.