Reading a Text File in Binary Mode

The WRFILE.C program that created and wrote to a file was fairly simple. Here's an equally simple program to read the file just created:

/* RDFILE.C: Read a file and print characters to the screen. */

#include <stdio.h>

#include <io.h>

main()

{

int c;

FILE *fp;

if( fp = fopen( "c:\\testfile.asc", "rb" ) )

{

while( (c = fgetc( fp )) != EOF )

printf( " %c\t%d\n", c, c );

printf( "\nEnd of file marker: %d", c );

fclose( fp );

}

else

printf( "Error in opening file\n" );

}

Although we plan to read the characters as eight-bit entities, the variable c should be declared as an int instead of a char. All of the incoming characters will be bytes the size of a char, except one.

When the file has been read from beginning to end, the end-of-file (EOF) marker appears on the stream. Within QuickC, an integer value of –1 (0xFFFF) represents EOF. To correctly identify this value, the variable c must be an integer.

Opening a File for Binary Reading

In the line below, the fopen function attempts to open a file. The first argument is the filename; the second is the type and mode, both of which may be literal strings or pointers to strings:

if( fp = fopen( "c:\\testfile.asc", "rb" ) )

The single backslash character used in path specifications must once again be represented by two backslashes. The file type is r for read-only. The additional b character forces the file to be read in binary mode instead of text mode. For a discussion of the differences between binary and text files, see the next page.

The fopen function returns a pointer to a FILE. If fopen fails, it returns a NULL pointer.

Finally, the if expression tests for a null value. The original WRFILE.C program included the != NULL test for inequality. Within the test expression of an if or a while, a 0 value is always false and any other value is considered true. In other words, should fp receive a valid nonzero address from fopen, the program continues. If something goes wrong, the remaining lines don't execute and the program drops through to the else.

Note that the expression above uses an assignment operator (=), not an equality operator (==). The value returned by fopen is always assigned to fp; they aren't being compared to each other. Then the if expression tests that value for truth or falsity.

Getting a Character

The key to the next line in RDFILE.C is the fgetc function, to which you pass a FILE pointer. It returns the next character from the given file:

while( (c = fgetc( fp )) != EOF )

The character is assigned to the integer variable c. As long as the character doesn't equal EOF, the while loop continues.

The end-of-file marker equals –1, but it's preferable to use the symbolic constant EOF. If the program is transported to another computer, you might find EOF has another value. Using the symbolic constant allows you to maintain compatibility between computers and operating systems.

For the same reason, it's preferable to test for NULL instead of assuming that NULL will always equal 0.

Viewing the File

Since there's only one line inside the while loop, it's not necessary to enclose it in curly braces. The variable c contains the character read from the file. It then can be printed:

printf( " %c\t%d\n", c, c );

The characters from the file print twice, once as a character (%c) and once as a decimal number (%d), separated by a tab stop. This printf statement repeats until fgetc (inside the while loop) finds no more characters in the file.