C65. C File Buffering


File Buffering
int fflush(FILE *stream);
void setbuf(FILE * restrict stream,char * restrict buf);
int setvbuf(FILE * restrict stream, char * restrict buf, int mode, size_t size);
Transferring data to or from a disk drive is a relatively slow operation. As a result, it isn't feasible for a program to access a disk file directly each time it wants to read or write a byte. The secret to achieving acceptable performance is buffering: data written to a stream is actually stored in a buffer area in memory; when it's full (or the stream is closed), the buffer is "Hushed" (written to the actual output device). Input streams can be buffered in a similar way: the buffer contains data from the input device; input is read from this buffer instead of the device itself. Buffering can result in enonnous gains in efficiency, since reading a byte from a buffer or storing a byte in a buffer lakes hardly any time at all. Of course, it takes time to transfer the buffer contents to or from disk, but one large "block move" is much faster than many tiny byte moves.
The functions in perform buffering automatically when it seems advantageous. The buffering lakes place behind the scenes, and we usually don't worry about it. On rare occasions, though, we may need to lake a more active role. If so, we can use the functions f flush, setbuf, and setvbuf.
When a program writes output to a file, the data normally goes into a buffer first. The buffer is flushed automatically when it's full or the file is closed. By call­ing f flush, however, a program can flush a file's buffer as often as it wishes. The call
fflush(fp);      /* flushes buffer for fp */
flushes the buffer for the file associated with fp. The call fflush(NULL); /* flushes all buffers */
flushes all output streams, f flush returns zero if it's successful and EOF if an error occurs.

setvbuf allows us to change the way a stream is buffered and to control the size and location of the buffer. The function's third argument, which specifies the kind of buffering desired, should be one of the following macros:
IOFBF (full buffering). Data is read from the stream when the buffer is empty or written to the stream when it's full.
IOLBF (line buffering). Data is read from the stream or written to the stream one line at a lime.
IONBF (no buffering). Data is read from the stream or written to the stream directly, without a buffer.


(All three macros are defined in .) Full buffering is the default for streams that aren't connected to interactive devices.
setvbuf's second argument (if it's not a null pointer) is the address of the desired buffer. The buffer might have static storage duration, automatic storage duration, or even be allocated dynamically. Making the buffer automatic allows its space to be reclaimed automatically at block exit: allocating it dynamically enables us to free the buffer when it's no longer needed, setvbuf's last argument is the number of bytes in the buffer. A larger buffer may give better performance; a smaller buffer saves space. setvbuf must be called after stream is opened but before any other operations are performed on it.
When using setvbuf or setbuf, be sure to close the stream before its buffer is deallocated. In particular, if the buffer is local to a function and has automatic stor­age duration, be sure to close the stream before the function returns.

No comments: