16.7: Arbitrary Input and Output (fread, fwrite)

Sometimes, you want to read a chunk of characters, without treating it as a ``line'' (as gets and fgets do) and certainly without doing any scanf-like parsing. Similarly, you may want to write an arbitrary chunk of characters, not as a string or a line. (Furthermore, the chunk might contain one or more \0 characters which would otherwise terminate a string.) In these situations, you want fread and fwrite.

fread's prototype is

	size_t fread(void *buf, size_t sz, size_t n, FILE *fp)
Remember, void * is a ``generic'' pointer type (the type returned by malloc), which can point to anything. It may make it easier to think about fread at first if you imagine that its first argument were char *. size_t is a type we haven't met yet; it's a type that's guaranteed to be able to hold the size of any object (i.e. as returned by the sizeof operator); you can imagine for the moment that it's unsigned int. fread reads up to n objects, each of size sz, from the stream fp, and copies them to the buffer pointed to by buf. It reads them as a stream of bytes, without doing any particular formatting or other interpretation. (However, the default underlying stdio machinery may still translate newline characters unless the stream is open in binary or "b" mode). fread returns the number of items read. It returns 0 (not EOF) at end-of-file.

Similarly, the prototype for fwrite is

	size_t fwrite(void *buf, size_t sz, size_t n, FILE *fp)

fread and fwrite are intended to write chunks or ``arrays'' of items, with the interpretation that there are n items each of size sz. If what you want to do is read n characters, you can call fread with sz as 1, and buf pointing to an array of at least n characters. The return value will be in units of characters. (Of course, you could write n characters by using similar arguments with fwrite.)

Besides reading and writing ``blocks'' of characters, you can use fread and fwrite to do ``binary'' I/O. For example, if you have an array of int values:

	int array[N];
you could write them all out at once by calling
	fwrite(array, sizeof(int), N, fp);
This would write them all out in a byte-for-byte way, i.e. as a block copy of bytes from memory to the output stream, i.e. not as strings of digits as printf %d would. Since some of the bytes within the array of int might have the same value as the \n character, you would want to make sure that you had opened the stream in binary or "wb" mode when calling fopen.

Later, you could try to read the integers in by calling

	fread(array, sizeof(int), N, fp);

Similarly, if you had a variable of some structure type:

	struct somestruct x;
you could write it out all at once by calling
	fwrite(&x, sizeof(struct somestruct), 1, fp);
and read it in by calling
	fread(&x, sizeof(struct somestruct), 1, fp);

Although this ``binary'' I/O using fwrite and fread looks easy and convenient, it has a number of drawbacks, some of which we'll discuss in the next chapter.

Read sequentially: prev next up top

This page by Steve Summit // Copyright 1996-1999 // mail feedback