0% found this document useful (0 votes)
10 views34 pages

5 Standard IO

The standard I/O library, created by Dennis Ritchie in 1975, manages buffer allocation and I/O operations across various operating systems. It supports both single-byte and multibyte character sets through file streams, with predefined streams for standard input, output, and error. The library provides various buffering methods, stream manipulation functions, and input/output operations, including character, line, and binary I/O, while ensuring efficient data handling and error management.

Uploaded by

wolaheg466
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views34 pages

5 Standard IO

The standard I/O library, created by Dennis Ritchie in 1975, manages buffer allocation and I/O operations across various operating systems. It supports both single-byte and multibyte character sets through file streams, with predefined streams for standard input, output, and error. The library provides various buffering methods, stream manipulation functions, and input/output operations, including character, line, and binary I/O, while ensuring efficient data handling and error management.

Uploaded by

wolaheg466
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

Standard I/O Library

Introduction

• The standard I/O library handles such details as buffer allocation and
performing I/O in optimal-sized chunks.
• The standard I/O library was written by Dennis Ritchie around 1975.
• This library is specified by the ISO C standard because it has been
implemented on many operating systems other than the UNIX System.
Streams and FILE Objects
• With the ASCII character set, a single character is represented by a single byte.
• With international character sets, a character can be represented by more than
one byte.
• Standard I/O file streams can be used with both single-byte and multibyte
(‘‘wide’’) character sets.
• A stream’s orientation determines whether the characters that are read and
written are single byte or multibyte.
• To reference the stream, we pass its FILE pointer as an argument to each
standard I/O function.
• Here, we refer to a pointer to a FILE object, the type FILE *, as a file pointer.
• The fwide function can be used to set a stream’s orientation.

• The fwide function performs different tasks, depending on the value of the
mode argument.
• If the mode argument is negative, fwide will try to make the specified stream
byte oriented.
• If the mode argument is positive, fwide will try to make the specified stream
wide oriented.
• If the mode argument is zero, fwide will not try to set the orientation, but
will still return a value identifying the stream’s orientation.
Standard Input, Standard Output, and Standard Error

• Three streams are predefined and automatically available to a process: standard


input, standard output, and standard error.
• These streams refer to the same files as the file descriptors STDIN_FILENO,
STDOUT_FILENO, and STDERR_FILENO, respectively.
• These three standard I/O streams are referenced through the predefined file
pointers stdin, stdout, and stderr.
• The file pointers are defined in the <stdio.h> header.
Buffering
• The goal of the buffering provided by the standard I/O library is to use
the minimum number of read and write calls.
• Three types of buffering are provided:
1. Fully buffered. Actual I/O takes place when the standard I/O buffer is filled.
• Files residing on disk are normally fully buffered by the standard I/O library.
• The buffer used is usually obtained by one of the standard I/O functions calling malloc
the first time I/O is performed on a stream.
• The term flush describes the writing of a standard I/O buffer. A buffer can be flushed
automatically by the standard I/O routines, such as when a buffer fills, or we can call the
function fflush to flush a stream. Unfortunately, in the UNIX environment, flush
means two different things:
• In terms of the standard I/O library, it means writing out the contents of a buffer, which may be
partially filled.
• In terms of the terminal driver, such as the tcflush function, it means to discard the data that's
already stored in a buffer.
2. Line buffered. The standard I/O library performs I/O when a newline
character is encountered on input or output.
• This allows us to output a single character at a time (with the standard I/O
fputc function), knowing that actual I/O will take place only when we finish
writing each line.
• Line buffering is typically used on a stream when it refers to a terminal, such as
standard input and standard output.
• Line buffering has two caveats:
• The size of the buffer that the standard I/O library uses to collect each line is fixed, so
I/O might take place if this buffer is filled before writing a newline.
• Whenever input is requested through the standard I/O library from either (a) an
unbuffered stream or (b) a line-buffered stream (that requires data to be requested from
the kernel), all line-buffered output streams are flushed. The reason for the qualifier on
(b) is that the requested data may already be in the buffer, which doesn't require data to
be read from the kernel. Obviously, any input from an unbuffered stream, item (a),
requires data to be obtained from the kernel.
3. Unbuffered. The standard I/O library does not buffer the
characters. For example:
• If we write 15 characters with the standard I/O fputs function, we
expect these 15 characters to be output as soon as possible, probably
with the write function from Section 3.8.
• The standard error stream is normally unbuffered so that any error
messages are displayed as quickly as possible, regardless of whether
they contain a newline.
• ISO C requires the following buffering characteristics:
• Standard input and standard output are fully buffered, if and only if they do not refer
to an interactive device.
• Standard error is never fully buffered.

• However, this doesn't tell us either of the following:


• Whether standard input and standard output are unbuffered or line buffered if they
refer to an interactive device
• Whether standard error should be unbuffered or line buffered

• Most implementations default to the following types of buffering:


• Standard error is always unbuffered.
• All other streams are line buffered if they refer to a terminal device; otherwise, they
are fully buffered.
• If we don’t like these defaults for any given stream, we can change the buffering
by calling either the setbuf or setvbuf function.

• These functions must be called after the stream has been opened (obviously,
since each requires a valid file pointer as its first argument) but before any other
operation is performed on the stream.
• At any time, we can force a stream to be flushed.

• The fflush function causes any unwritten data for the stream to be
passed to the kernel.
• As a special case, if fp is NULL, fflush causes all output streams to be
flushed.
Opening a Stream
• The fopen, freopen, and fdopen functions open a standard I/O stream.
The differences in these three functions are as follows:
1. The fopen function opens a specified file.

2. The freopen function opens a specified file on a specified stream, closing the stream
first if it is already open. If the stream previously had an orientation, freopen clears it.
This function is typically used to open a specified file as one of the predefined streams:
standard input, standard output, or standard error.

3. The fdopen function takes an existing file descriptor, which we could obtain from the
open, dup, dup2, fcntl, pipe, socket, socketpair, or accept functions, and
associates a standard I/O stream with the descriptor. This function is often used with
descriptors that are returned by the functions that create pipes and network
communication channels. Because these special types of files cannot be opened with the
standard I/O fopen function, we have to call the device-specific function to obtain a file
descriptor, and then associate this descriptor with a standard I/O stream using fdopen.
When a file is opened for reading and writing (the plus sign in the
type), two restrictions apply.
• Output cannot be directly followed by input without an intervening
fflush, fseek, fsetpos, or rewind.

• Input cannot be directly followed by output without an intervening


fseek, fsetpos, or rewind, or an input operation that encounters an
end of file.
• An open stream is closed by calling fclose.

• Any buffered output data is flushed before the file is closed. Any input data that
may be buffered is discarded. If the standard I/O library had automatically
allocated a buffer for the stream, that buffer is released.
• When a process terminates normally, either by calling the exit function directly
or by returning from the main function, all standard I/O streams with unwritten
buffered data are flushed and all open standard I/O streams are closed.
Reading and Writing a Stream
• The three types of unformatted I/O:
1. Character-at-a-time I/O. We can read or write one character at a time, with
the standard I/O functions handling all the buffering, if the stream is
buffered.
2. Line-at-a-time I/O. If we want to read or write a line at a time – using
fgets and fputs.
3. Direct I/O. This type of I/O is supported by the fread and fwrite
functions. For each I/O operation, we read or write some number of
objects, where each object is of a specified size. These two functions are
often used for binary files where we read or write a structure with each
operation.
Input Functions
• Three functions allow us to read one character at a time.
The function getchar is defined to be equivalent to getc(stdin). The difference
between getc and fgetc is that getc can be implemented as a macro, whereas
fgetc cannot be implemented as a macro. This means three things:
1. The argument to getc should not be an expression with side effects, because
it could be evaluated more than once.
2. Since fgetc is guaranteed to be a function, we can take its address. This
allows us to pass the address of fgetc as an argument to another function.
3. Calls to fgetc probably take longer than calls to getc, as it usually takes
more time to call a function.
• Note that these functions return the same value whether an error occurs or the
end of file is reached.
• To distinguish between the two, we must call either ferror or feof.

In most implementations, two flags are maintained for each stream in the FILE
object:
• An error flag
• An end-of-file flag
Both flags are cleared by calling clearerr.
Output Functions
• Output functions are available that correspond to each of the input functions

• As with the input functions, putchar(c) is equivalent to putc(c, stdout),


and putc can be implemented as a macro, whereas fputc cannot be
implemented as a macro.
Line-at-a-Time I/O
• Line-at-a-time input is provided by the two functions, fgets and gets.

• Both specify the address of the buffer to read the line into. The gets function
reads from standard input, whereas fgets reads from the specified stream.
• With fgets, we have to specify the size of the buffer, n. This function reads up
through and including the next newline, but no more than n − 1 characters, into
the buffer
• The buffer is terminated with a null byte.
• If the line, including the terminating newline, is longer than n − 1, only a partial
line is returned, but the buffer is always null terminated.
• Another call to fgets will read what follows on the line.
• The gets function should never be used. The problem is that it doesn’t allow
the caller to specify the buffer size.
• This allows the buffer to overflow if the line is longer than the buffer, writing
over whatever happens to follow the buffer in memory.
• Line-at-a-time output is provided by fputs and puts.

• The function fputs writes the null-terminated string to the specified stream. The
null byte at the end is not written.
• The puts function writes the null-terminated string to the standard output,
without writing the null byte. But puts then writes a newline character to the
standard output.
Binary I/O
• The following two functions are provided for binary I/O.

These functions have two common uses:


1. Read or write a binary array.
2. Read or write a structure.
• Both fread and fwrite return the number of objects read or written.

• For the read case, this number can be less than nobj if an error occurs or if the
end of file is encountered.
• In this situation, ferror or feof must be called.

• For the write case, if the return value is less than the requested nobj, an error
has occurred.
Positioning a Stream
There are three ways to position a standard I/O stream:
1. The two functions ftell and fseek. They have been around since Version 7,
but they assume that a file’s position can be stored in a long integer.
2. The two functions ftello and fseeko. They were introduced in the Single
UNIX Specification to allow for file offsets that might not fit in a long integer.
They replace the long integer with the off_t data type.
3. The two functions fgetpos and fsetpos. They were introduced by ISO C.
They use an abstract data type, fpos_t, that records a file’s position. This
datatype can be made as big as necessary to record a file’s position.
• For a binary file, a file’s position indicator is measured in bytes from the
beginning of the file.
• The value returned by ftell for a binary file is this byte position. To position a
binary file using fseek, we must specify a byte offset and indicate how that offset
is interpreted.
• The values for whence are the same as for the lseek function: SEEK_SET means
from the beginning of the file, SEEK_CUR means from the current file position,
and SEEK_END means from the end of file.
• For text files, the file’s current position may not be measurable as a simple byte
offset.
• Again, this is mainly under non-UNIX systems that might store text files in a
different format.
• To position a text file, whence has to be SEEK_SET, and only two values for
offset are allowed: 0—meaning rewind the file to its beginning—or a value that
was returned by ftell for that file.

• A stream can also be set to the beginning of the file with the rewind function.
• The ftello function is the same as ftell, and the fseeko function is the
same as fseek, except that the type of the offset is off_t instead of long.
• The fgetpos function stores the current value of the file’s position indicator in
the object pointed to by pos.
• This value can be used in a later call to fsetpos to reposition the stream to
that location.

You might also like