ECE 209 -- Files
Definitions
file |
A sequence of bytes with a name maintained by the operating system.
Example filenames include
/home/clauss/NiceList.txt and
C:\Users\Claus\NiceList.txt.
|
FILE pointer |
The C value of type FILE * . This mysterious
value is created when files are opened and is used in almost
all C I/O operations. Evidently, a lot of stuff is stored in
a FILE , but no one wants to know what it is.
|
stream |
Not everything with a filename is a real file. Examples
include named pipes in Unix and Windows and special
devices like /dev/null
and /dev/random in Unix and
NUL and
COM1 in Windows. C and, especially, C++ gurus
always call opened files or file-like entities streams.
In fact, the terms stream and
FILE pointer are often used as synonyms.
|
mode |
The way in which a stream is being used: reading, writing, or both.
Can also apply to opening files as binary or text.
(In Unix, mode also confusingly refers to the protection
associated with a file.)
|
sequential access |
Reading or writing a stream in serial order, that is, from the
first byte to the last. These is how files are usually processed.
|
random access |
Reading or writing a stream by moving directly
to specific points within the file. These points are not
random. They are chosen by the C program.
This is rarely done.
|
file offset |
Thus is the point where an application is presently reading
or writing in a stream. It is expressed as the number of bytes from
the beginning of a file. Sometimes called the
file position indicator
or even (especially by non-C programmers) the file pointer
which is easily confused with the FILE pointer.
|
binary mode |
The values written and read by the C application are exactly
those the are stored within the file as maintained by the operating
system. When C is run on a Unix computer, all file
operations are performed in binary mode. For this reason, Unix
does not distinguish between binary and text mode.
|
text mode |
In Unix and Mac OS X operating systems, lines of text are
separated by a single character, the linefeed (aka, '\n'
or new line or ASCII 10). In the Windows operating system,
lines of text are separated by two characters,
the carriage return (aka, '\r' or ASCII 13) and then
the linefeed. To maintain program portability, when a C program
writes "\n" to a text file in Windows, the C I/O
library actually writes "\r\n" . A similar trick
is done when reading text files. (C++ "solves" this problem
by using a special constant endl to write the
end-of-line sequence.)
|
standard files |
When Unix programs are started they are given three opened file
descriptors (the operating system view of a file): standard
input, for reading characters; standard output, for writing
characters; and standard error, for writing argent output.
Windows and Mac OS provide similar file descriptors. In C,
these are represented by three FILE pointers:
stdin , stdout , and stderr .
|
buffer |
When a C program reads or writes data, the C I/O system does
not directly request data from the operating system. Instead
it maintains a buffer of data that is sent to the
operating system when appropriate. This approach significantly
improves program performance. Unfortunately, there are
time when it is necessary to flush the buffer to
make sure changes are written to the file system or the terminal.
|
Opening and closing files
fopen |
Opens a file and associates a stream with it.
Returns NULL if the open fails.
|
fclose |
Closes a stream. Very rarely fails. |
stdin |
Standard input stream |
stdout |
Standard output stream |
stderr |
Standard error stream |
Reading streams
fscanf |
Complicated function for formatted input. |
fgetc |
Reads a single character. |
fgets |
Reads a line. |
fread |
Reads raw bits from the stream. |
Writing streams
fprintf |
Complicated function for formatted output. |
fputc |
Writes a single character. |
fputs |
Write a line. |
fwrite |
Writes raw bits to the stream. |
Random access I/O
fseek |
Moves the offset of a stream. |
ftell |
Returns the current offset within a stream. |
Buffering
fflush |
Really writes buffered output of stream. |
ungetc |
Unreads a characters. Allows peeking ahead. Best to avoid. |
Example program for writing a file
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int arraySize ;
FILE *fileStream ;
int row, col ;
if (argc != 3
|| (arraySize = atoi(argv[2])) <= 0) {
fprintf(stderr, "Usage: %s OutputFileName SizeOfArray\n", argv[0]) ;
return(EXIT_FAILURE) ;
}
if ((fileStream = fopen(argv[1], "w")) == NULL) {
fprintf(stderr, "Unable to open %s for output\n", argv[1]) ;
return(EXIT_FAILURE) ;
}
for (row=0; row<arraySize; ++row) {
for (col=0; col<row; ++col) {
fputs("0,", fileStream) ;
}
fputs("1,",fileStream) ;
for (col=row+1; col<arraySize; ++col) {
fputs("0,", fileStream) ;
}
fputc('\n', fileStream) ;
}
fclose(fileStream) ;
return(EXIT_SUCCESS) ;
}
Initializing a password check file
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int numberOfSlots ;
FILE *fileStream ;
int wordNum ;
unsigned int zilch = 0 ;
if (argc != 3
|| (numberOfSlots = atoi(argv[2])) <= 0) {
fprintf(stderr, "Usage: %s OutputFileName NumberOfSlots\n", argv[0]) ;
return(EXIT_FAILURE) ;
}
if ((fileStream = fopen(argv[1], "w")) == NULL) {
fprintf(stderr, "Unable to open %s for output\n", argv[1]) ;
return(EXIT_FAILURE) ;
}
for (wordNum=0; wordNum<numberOfSlots; ++wordNum) {
if (fwrite((void *)&zilch, sizeof zilch, 1, fileStream) != 1) {
fprintf(stderr, "Failure writing to %s\n", argv[1]) ;
return(EXIT_FAILURE) ;
}
}
fclose(fileStream) ;
return(EXIT_SUCCESS) ;
}
Updating a password check file
#include <stdio.h>
#include <stdlib.h>
int HashIt(char *String, int Range) {
unsigned int R = 0 ;
while (*String) {
R = R*209 + *String ;
++String ;
}
return ((int) (R % Range)) ;
}
int main(int argc, char **argv) {
int numberOfSlots ;
FILE *fileStream ;
char line[100] ;
if (argc != 2) {
fprintf(stderr, "Usage: %s PasswordCheckFile\n", argv[0]) ;
return(EXIT_FAILURE) ;
}
if ((fileStream = fopen(argv[1], "r+")) == NULL) {
fprintf(stderr, "Unable to open check file %s\n", argv[1]) ;
return(EXIT_FAILURE) ;
}
if (fseek(fileStream, 0L, SEEK_END)
|| (numberOfSlots = ftell(fileStream)/sizeof(int)) <= 0) {
fprintf(stderr, "Excuse me, Dave. There's a problem with %s\n", argv[1]) ;
return(EXIT_FAILURE) ;
}
while(fgets(line, sizeof line - 1, stdin) != NULL) {
int numberTimes ;
int hashVal = HashIt(line, numberOfSlots ) ;
if (fseek(fileStream, hashVal*sizeof(int), SEEK_SET)
|| fread((void *)&numberTimes, sizeof(int), 1, fileStream) != 1) {
fprintf(stderr, "Excuse me, Dave. There's a problem reading %s\n",
argv[1]) ;
return(EXIT_FAILURE) ;
}
++numberTimes ;
fprintf(stdout, " used about %d times\n", numberTimes) ;
if (fseek(fileStream, -sizeof(int), SEEK_CUR)
|| fwrite((void *)&numberTimes, sizeof(int), 1, fileStream) != 1) {
fprintf(stderr, "Excuse me, Dave. There's a problem writing %s\n",
argv[1]) ;
return(EXIT_FAILURE) ;
}
}
return(EXIT_SUCCESS) ;
}