Opening a File in the Raw

The fopen() function opens a file or stream for formatted input. The “formatted” is where the function gets its f prefix, which I always thought stood for file. It doesn’t. The fopen() function is the formatted file (and stream) function, the open() function is for low-level, unformatted file access.

Rare is the beginner book or tutorial that covers the open() function, primarily because it deals with low-level, unformatted file access and it’s not really required to open a file. Therefore, it’s skipped or glossed over. Yet, the function is worth some discovery.

Before exploring the open() function, here’s an example of the fopen() function, which accesses the file gettysburg.txt and sends its contents to standard output:

#include <stdio.h>

int main()
{
    const char filename[] = "gettysburg.txt";
    FILE *fp;
    int ch;

    fp = fopen(filename,"r");
    if( fp==NULL )
    {
        fprintf(stderr,"Unable to open %s\n",filename);
        return(1);
    }

    while( !feof(fp) )
    {
        ch = fgetc(fp);
        if( ch==EOF )
            break;
        fputc(ch,stdout);
    }
    fclose(fp);

    return(0);
}

The fopen() function’s arguments are a filename string and a string representing the opening mode. The value returned is a FILE pointer, a handle containing details and other trivia about the open file. Upon success, the file is opened for formatted input and output, depending upon the second argument.

The open() function, on the other hand, offers a different definition. Prototyped in the fnctl.h header, here’s its man page (2) format:

int open(const char *path, int oflag, ...);

The first argument (const char *path) is the same as fopen(), a filename string or the pathname to a device to open. The argument (oflag) is one or more constant expressions or flags that set how the file is to be opened. These constants, also defined in fnctl.h, must include one of these three:

O_RDONLY Open the file read-only.
O_WRONLY Open the file write-only.
O_RDWR Open the file for reading and writing.

Additional flags set a specific file-opening mode and are logically OR’d with each other. For example, the O_CREAT flag creates a file that doesn’t exist; unlike the fopen() function, using open() on a file that doesn’t exist without specifying the O_CREAT flag returns an error.

The third argument is documented differently, depending on the source. I have no idea what it does, but it’s not required for the examples on this blog.

The open() function returns a non-negative integer value, a file descriptor. Upon failure, the value -1 is returned. This return value is a huge difference between open() and fopen().

File descriptor values range from zero on up, with file descriptors 0, 1, and 2 all preset (and reserved) by the operating system to the following standard I/O devices: standard input (stdin), standard output (stdout), and standard error (stderr), respectively. These constants are also defined in the unistd.h header file as: STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO.

Just as the companion to fopen() is open(), the companion to fclose() is close(). This function is defined in the unistd.h header file (not fcntl.h), and it requires a single argument, the file descriptor integer returned by the open() function.

The following code opens the file gettysburg.txt as did the first example, but uses the open() function. The file is opened and closed; no data is read.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    const char filename[] = "gettysburg.txt";
    int fdes;

    fdes = open(filename,O_RDONLY);
    if( fdes==-1 )
    {
        fprintf(stderr,"Unable to open %s\n",filename);
        return(1);
    }

    printf("'%s' opened for low-level, unformatted reading\n",filename);

    close(fdes);

    return(0);
}

At Line 10, the open() function opens the file gettysberg.txt (referenced by variable filename) in read-only mode. The file descriptor returned is kept in the fdes variable, which is tested at Line 11.

Line 19 closes the opened file, using the close() function with file descriptor variable fdes.

Here’s a sample run:

'gettysburg.txt' opened for low-level, unformatted reading

In next week’s Lesson, I explore reading text from a file opened by using the open() function, and sending the text to standard output.

Leave a Reply