/**
@file fileIO.c
@author Mitch Richling <http://www.mitchr.me/>
@Copyright Copyright 1995 by Mitch Richling. All rights reserved.
@brief UNIX I/O routines@EOL
@Keywords UNIX file I/O
@Std ISOC POSIX UNIX98
Two general approaches are taken for file I/O in C on a
UNIX platform: UNIX I/O and ANSI/ISO C I/O. This
program demonstrates the UNIX I/O routines. It is
important not to mix ANSI/ISO C I/O with UNIX I/O on the
same file. This will hopelessly confuse your program.
Functions exist in the UNIX library to let you do this,
but it is best to simply avoid the mess. On a side
note, do not mix C++ I/O with UNIX or ANSI/ISO C I/O.
Again, methods exist to make this work, but it is best
to simply pick an I/O library and stick to it. :)
Most UNIX I/O functions can error with an EINTR error.
In general if this error is seen, the function should be
re-attempted. This code doesn't demonstrate this. Also
this code doesn't demonstrate the complete behavior of
of the write call with respect to partial success. Both
of these interesting problems are tackled in the example
program called IOerrors.c. The approach taken in this
code is typical of file I/O found in many UNIX programs.
The more exotic error handling found in IOerrors.c is
normally only seen in network programs.
@Tested
- Solaris 2.8
- MacOS X.2
- Linux (RH 7.3)
*/
#include <sys/stat.h> /* UNIX stat POSIX */
#include <sys/types.h> /* UNIX types POSIX */
#include <sys/uio.h> /* BSD I/O BSD */
#include <stdio.h> /* I/O lib ISOC */
#include <string.h> /* Strings ISOC */
#include <dirent.h> /* UNIX dirs POSIX */
#include <errno.h> /* error stf POSIX */
#include <stdlib.h> /* Standard Lib ISOC */
#include <unistd.h> /* UNIX std stf POSIX */
#include <fcntl.h> /* UNIX file ctrl UNIX */
int main(int argc, char *argv[]);
int main(int argc, char *argv[]) {
char buf[255]; /* A character buffer to use for I/O. */
char *fileName = "foo";
int returnValue;
int readNum;
int FD;
/* FD stands for File Descriptor. In ANSI/ISO C I/O one uses a FP
or File Pointer. For UNIX a FD is simply an integer, while
ANSI/ISO C uses a struct. ANSI/ISO C restricts a program to 254
open files because each file is uniquely identified by an 8-bit
integer. The number of open files possible with UNIX I/O
varies, but is generally much higher than ANSI/ISO C. */
/* ************************************************************************** */
/* First we create/overwrite a file named foo. */
/* Just as with ANSI/ISO C, we must open the file first. This can fail.
If errno is EINTR, the open should be retried. */
if((FD = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
perror("ERROR: File open");
exit(10);
} /* end if */
/* Report what file descriptor we got. */
printf("We opened the file '%s' and got file descriptor number %d\n", fileName, FD);
strcpy(buf, "This is the first line of the file\n");
returnValue = write(FD, buf, strlen(buf)); /* How to write a string. */
/* The return of the write is the number of bytes written. If it is less
than the request, an attempt to write the rest of the string should be
made. This function can error because of an interrupt (errno==EINTR).
If an EINTR is encountered, the write should be re-attempted. */
if(returnValue < 0) {
perror("ERROR: File write");
exit(11);
} /* end if */
printf("The write returned %d\n", returnValue);
/* Write the first 2 bytes of the integer stored in returnValue.
This won't work if the integer is not at least 2 bytes long. :) */
returnValue = write(FD, &returnValue, 2);
if(returnValue < 0) {
perror("ERROR: File write");
exit(12);
} /* end if */
printf("The write returned %d\n", returnValue);
/* We must close the file to free up system resources. If we forget to close
the file, then it will be closed for us when our program exits. */
if(close(FD) < 0) { /* Yes, we check for errors. */
perror("ERROR: File open");
exit(13);
} /* end if */
/* ************************************************************************** */
/* Now we read the file we just wrote. */
/* First we open the file. This can fail.
If errno is EINTR, the open should be retried. */
if((FD = open(fileName, O_RDONLY)) < 0) {
perror("ERROR: File open");
exit(10);
} /* end if */
/* Report what file descriptor we got. */
printf("We opened the file '%s' and got file descriptor number %d\n", fileName, FD);
/* We now read the data in 1 byte chunks. Larger reads will be demonstrated
later. read can error with EINTR, and should be re-attempted if this error
occurs. read returns 0 at EOF, and -1 upon error. */
printf("Data in file:\n");
while((returnValue = read(FD, buf, 1)) > 0) {
printf("%c", buf[0]);
} /* end while */
if(returnValue == 0)
printf("Finished reading all the data.\n");
if(returnValue < 0) {
perror("ERROR: File read");
exit(11);
} /* end if */
/* Now that we have read the file one byte at a time, it is a good idea to see how
to read the data more than one byte at a time. We could close the file now and
reopen it, but instead we demonstrate the seek function. It is much like the
ANSI/ISO C function fseek. We will use this function to "rewind" the filepointer
so that we can reread the file from the start. This also demonstrates that reading
the EOF marker is not special for UNIX I/O. Unlike some I/O libraries, reading EOF
won't automatically close the file. */
/* Here it is. Rewind the file to the start. */
lseek(FD, 0, SEEK_SET);
/* We now read the data in 250 byte chunks. Note that we read the WHOLE file
in one step. It is possible to query the size of the file using stat(2), and
then to read in most files in one big chunk. */
readNum = 0;
printf("Data in file(second read):\n");
while((returnValue = read(FD, buf, 250)) > 0) {
buf[returnValue] = '\0';
readNum++;
printf("Read #%d: %s", readNum, buf);
} /* end while */
if(returnValue == 0)
printf("Finished reading all the data.\n");
if(returnValue < 0) {
perror("ERROR: File read");
exit(11);
} /* end if */
/* Finally we close the file -- after having read it in twice. */
if(close(FD) < 0) {
perror("ERROR: File close");
exit(13);
} /* end if */
printf("Normal exit.\n");
exit(0);
} /* end func main */
Generated by GNU enscript 1.6.4.