Standard Library IO
Input and output functions are not part of the C language; the ANSI standard defines the relevant library functions
Inputs and outputs <>
A streamstream is the source or destination of data associated with a device.
- Text stream: a sequence of lines of text
Features that may vary from system to system, such as maximum line length and line terminators - Binary stream: unprocessed sequence of bytes
When the program is running, stdin, stdout, stderr are turned on by default.
Standard IO Constants
- EOF: end of file, the actual value is a few characters to avoid confusion
- FOPEN_MAX: the maximum number of files that a program can have open at the same time, compiler dependent, value at least 8
- FILENAM_MAX: the longest file name supported by the compiler
file streaming operation
The file pointer points to a structure that contains information about the file, including buffers, read and write status, etc.
Open and Close
FILE *fopen(const char *filename, const char *mode); // open a file stream
/*
mode.
* r, open for reading
* w, opens or creates a write, deletes the original content.
* a, open or create, append to end of file.
* +, update, read or write, need to perform fflush or locate before cross operation
* r+, open file for update (read and write)
* w+, create file update, delete original content
* a+, open or create file, end-of-file update
* b, binary stream mode
The return value should always be checked
*/
FILE *freopen(const char *filename, const char *mode, FILE *stream); // Close then open the stream.
FILE *fdopen(int fd, const char *type); // POSIX standard, often used for descriptors returned by functions that create pipelines and network channels, not directly opened by fopen.
// type arguments: r, w, a, (+)
// Note that in read/write mode the locator function needs to be called between reads and writes.
int fclose(FILE *stream); // Flush the output buffer, free the system buffer, and close the stream.
int fileno(FILE *fp); // The POSIX standard.
Orientation of the stream
Standard IO can be used for both single-byte and multi-byte character sets, as determined by the orientation of the stream.
- The freopen function clears the orientation of a stream
- The fwide function sets the orientation of the stream,
#include <>
#include <>
int fiwde(FILE *fp, int mode);
/*
mode<0, trying to set to single byte
mode>0, attempt to set to multi-byte
mode=0, no orientation set, return stream orientation
will not change the already set stream orientation
*/
File Manipulation Functions
rename
int remove(FILE *stream); // Delete file
int rename(const char *oldname, const char *newname); // Rename a file
temporary file
FILE *tmpfile(void); // Create a temporary file in `wb+` mode, automatically deleting it when closing or at the end of the program
// Implement on tmpnam, create the file, unlink it (without deleting the contents), and the file will be closed automatically at the end of the program.
char *tmpnam(char s[L_tmpnam]); // create string with different existing file name, NULL returns pointer to static array
// UNIX advantage is that there is no time gap to avoid other processes creating files with the same name
char *mkdtemp(char *temple); // Create a directory
int mkstmp(char *temple); // Create files, do not delete them automatically.
buffer operation
Standard IO provides buffering to minimize the number of read/write calls
-
Full buffer: actual IO operations are performed only when the buffer is full
-
Line buffer: IO operations are performed only when a line break is encountered
- The length of the line buffer is fixed, and IO operations are performed when the line buffer is full, even if there are no line breaks.
- Standard IO requires that fetching data from unbuffered or row buffers (which require requesting data from the kernel) immediately flushes the output streams of all row buffers
-
Without buffer
ISO C standard
- Fully buffered if and only if standard inputs and standard outputs do not point to the interactive device
- Standard errors won't be fully buffered
default situation
- Standard error without buffering
- Row-buffered if it is a stream to an end device, otherwise fully buffered
Type of buffer replacement: after the stream has been opened and before any operations are performed
int fflush(FILE *stream); // flush the buffer
/*
- For output streams, flushes the contents of the write buffer to the destination file.
- For input streams, the result is undefined
- NULL, flushes all buffers.
Practical tip: call fflush immediately after each debug printf.
*/fflush
int setvbuf(FILE *stream, char *buf, int mode, size_t size); // Buffers must be set before reading or writing is performed.
/*
mode.
- _IOFBF full buffer
- _IOLBF line buffer
- _IONBF no buffering
*/
void setbuf(FILE *stream, char *buf); // char buf[BUFSIZ]
/*
- buff is NULL, disable buffering
- Otherwise, equivalent to `_IOFBF`.
// Note: don't use automatic variable types for buf, use system buffers or dynamically allocated memory if possible.
*/
#TODO# Viewing Stream Buffer Status Programming the UNIX Advanced Environment
read-write streaming operation
Character IO
#TODO#Family of Input-Output Functions C and Pointers P301
int fgetc(FILE *stream); // unsigned char to int, compatible with EOF
int getc(FILE *stream); // Equivalent to fgetc, note that it is implemented as a macro.
int getchar(void); // equivalent to getc(stdin)
int fputc(int c, FILE *stream).
int putc(int c, FILE *stream); // Equivalent to fputc, note the implementation as a macro
int putchar(int c); // equivalent to fputc(stdout)
// Only fgetc and fputc are functions, the others are macros.
int ungetc(int c, FILE *stream); // Returns the character to the stream, depending on the current location.
// Unlike writes, only the stream itself is involved, not the device memory.
Unformatted line IO
char *fgets(char *s, int n, FILE *stream); // Automatically include line breaks, \n for \0, up to n-1.
char *gets(char *s); // Do not automatically include newlines. No buffer length parameter, may lead to out-of-bounds; not recommended, deprecated
int fputs(const char *s, FILE *stream); // Do not automatically include newlines \n, enter any number of newlines character-by-character
int puts(const char *s); // automatically add newlines \n
ssize_t getline(char **lineptr, size_t *n, FILE *stream); // Dynamically allocate memory based on input.
// Dynamically allocate memory based on input, no need to predetermine the maximum length of the input string.
// Replace line breaks with string terminators '\0' in stored strings.
Formatting IO
int fprintf(FILE *stream, const char *format, ...) ;
int printf(const char *format, ...) ; // Equivalent to `fprintf(stdout, fotmat, ...). ; // Equivalent to `fprintf(stdout, fotmat, ...) `
int sprintf(char *s, const char *format, ...) ; // Equivalent to `fprintf(stdout, fotmat, ...). ; // Includes terminator NUL, no length parameter, possible out-of-bounds overflow
int snprintf(char *buf, szie_t n, const char *format, ...) ; // Truncate overrun. ; // truncate beyond, return negative value for error
int fdprintf(int fd, const char *format, ...) ;
// Variant with variable-length parameter list
int vprintf(const char *format, va_list arg) ;
int vfprintf(FILE *stream, const char *format, va_list arg); ; // Variant of variable-length parameter list.
int vsprintf(char *s, const char *format, va_list arg);
Convert the format:
-
Normal characters: copy to output stream
-
Conversion description: format conversion of control parameters
-
Beginning %
-
Flag [optional]
-
-
Left-aligned, defaults to right-aligned -
+
Show plus or minus sign - Space Signed value conversion
-
0
Fill 0 when width is insufficient -
#
Specify another form of output
-
-
Width value [optional]: specify the minimum field width
-
Precision value [optional]: starting with a dot followed by a decimal value
-
length modifier [optional]: specify the length of the parameter
- h on the basis ofshort/unsigned short exports
- l Output by long/unsigned long
- L Output as long double
-
End: Convert characters, d, c, s, f, x, etc.
-
int fscanf(FILE *stream, const char *format, ...) ;
int scanf(const char *format, ...) ;
int sscanf(const char *s, char *format, ...) ; int sscanf(const char *s, char *format, ...) ;
int fdscanf(int fd, const char *format, ...) ; int fdscanf(int fd, const char *format, ...) ;
// Variant with variable-length argument list ...
- Arguments must be pointers
- to the end of the file or error return EOF, otherwise return the actual number of characters entered
conversion format
-
Spaces or tabs
-
Normal characters: match the next input
-
Conversion instructions
- Start sign
%
[Optional] - assignment mask symbol
*
[Optional] - Maximum field width value [optional]
- qualifier
h\l\L
The length of the specified parameter [optional]. - End flag: converts characters d, f, c, s, x, etc.
- Start sign
#TODO #4 usage scenarios P309
Binary IO
Direct IO/Binary IO, usually one structure at a time, able to handle null bytes and newlines.
Note: It can only be used on the same system, the offset alignment and storage format may be different on different systems. Therefore, network communication requires a specified specification.
size_t fread(void *buffer, size_t size, size_t nobj, FILE *stream);
size_t fwrite(const void *buffer, size_t size, size_t nobj, FILE *stream).
/* The return value is the number of elements actually read or written, not the number of bytes.
fread: less than nobj, error or EOF, need to distinguish further
fwrite: less than nobj, error or EOF.
*/
memory flow
File-independent, byte IO directly between buffer and main memory. great for strings.
Linux support.
FILE *fmemopen(void *buf, size_t size, const char *type); // buf=null, read/write is meaningless; handling of null bytes is very specialized
FILE *open_memstream(char **bufp, size_t sizep); // byte-oriented streams
FILE *open_wmemstream(wchar_t **bufp, size_t *sizep); // wide-byte-oriented streams
File Locator Functions
- Binary files: use byte offsets, do not necessarily support SEEK_END
- Text file: format different can't use bytes, orgin=SEEK_SET, offset=0/ftell
int fseek(FILE *stream, long offset, int origin);
/*
- Binary file
- origin
- `SEEK_SET` The beginning of the file.
- `SEEK_CUR` current position
- `SEEK_END` end of file, may not be supported
- Text file
- `SEEK_SET`; offset is 0 or `ftell` returns value
- `SEEK_CUR`/`SEEK_END`: offset can only be 0
Caution.
- End-of-line indicators will be cleared
- Returned characters will be discarded
- Switching between read and write operations in update mode
*/
long ftell(FILE *stream).
void rewind(FILE *stream); // reset to start position
// Equivalent to `fseek(stream, 0L, SEEK_SET); clearerr(stream);`
// off_t, more than32classifier for honorific people UNIX (an official) standard
off_t ftello(FILE *fp);
int seeko(FILE *fp, off_t offset, int origin);
// fpos_t ISO C standard, more generic
int fgetpos(FILE *stream, fpos_t *ptr);
int fsetpos(FILE *stream, const fpos_t *ptr).
error handler
A status indicator is set when an error occurs or when the end of the file is reached.
The integer expression errno contains the error number, defined in the <>
- errno is only set when the library function fails, successful execution does not change errno.
- No function will ever set a constant to 0.
/* ----- stream error -----*/
int feof(FILE *stream); // stream set end-of-file indicator, return non-zero value
int ferror(FILE *stream); // stream set error indicator, return non-zero value
int clearerr(FILE *stream); // Clear all indicators for the stream.
#include <>
char *strerror(int crrno); // map the error message
#include <>
int perror(const char *s); // prints the string and errno error message
// similar to fprintf(stderr, "%s: %s\n", s, "error essage");
Alternatives to Standard IO
Standard IO is not efficient, calling row IO requires two copies of the data
- Fast IO fio: use pointers instead of copying whole lines
- sfio: increase speed while promoting IO flows
- mmap
Implementation of lower memory requirements for embedded systems
- uClibc C Library
- Newlib C Library
consultation
- C Programming Language
- Advanced Programming for the UNIX Environment