5 Standard I/O Library (标准I/O库)
5.1 Introduction (介绍)
The standard I/O library handles such details as buffer allocation and performing I/O in optional-sized chunks, obviating our need to worry about using the correct block size. (标准I/O库处理像缓存分配,在可选的块间执行等细节,省却我们需要选择使用正确的块大小的担心。)
5.2 Streams and FILE Objects (Streams 和 FILE 对象)
When a file is opened, a file descriptor is returned, and that descriptor is then used for all subsequent I/O operations. (当打开文件后返回一个文件描述符,这个描述符用于随后的所有I/O操作。)
With the ASCII character set, a single character is represented by a single byte. With international character set, a character can be represented by more than one byte. (对于ASCII字符集,一个字节表示一个字符。对于国际字符集,一个字符可能用几个字节表示。)
Standard I/O file streams can be used with single-byte and multibyte("wide") character sets. (标准I/O文件流可以使用单字节和多字节字符集。)
#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp, int mode);
Returns: positive if stream is wide-oriented, negative if stream is byte-oriented, or 0 if stream has no orientation.
The freopen function will clear a stream's orientation; the fwide function can be used to set a stream's orientation. (freopen函数可以清除流的取值。fwide函数可以设置流的取值。)
If the mode argument is negative, fwide will try to make the specified stream byte-oriented. (mode参数为负数时,fwide尝试指定流取单字节模式。)
If the mode argument is positive, fwide will try to make the specified stream wide-oriented. (mode参数为正数时,fwide尝试指定流取多字节模式。)
If the mode argument is zero, fwide will not try to set the orientation, but will still retuan a value identifying the stream's orientation. (mode为0时,fwide不设置流的值。但仍然返回一个值标识流的取值。)
Note that fwide will not change the orientation of a stream that is already oriented. (注意fwide函数不会改变一个已经有值的流。)
Also note that there is no error return. (另外要注意fwide函数不会返回错误。)
To reference the stream, we pass its FILE pointer as an argument to each standard I/O function. (要引用流,我们通过传递FILE指针作为每个标准I/O函数的参数。)
5.3 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 file as the file descriptors STD_FILENO, STDOUT_FILENO, STDERR_FILENO. (这些流指向STD_FILENO, STDOUT_FILENO, STDERR_FILENO描述符。)
These three standar I/O streams are referenced through the predefined file pointers stdin, stdout, stderr. The file pointer are defined in the <stdio.h> header. (这三个标准I/O流通过预先定义的文件指针:stdin, stdout, stderr被引用。这些指针定义在<stdio.h>头文件中。)
5.4 Buffering (缓存)
The goal of the buffering provided by the standard I/O library is to use the minimum number of read and write calls. (标准I/O库提供缓存的目的是使用最少次数的read和write调用。)
Fully buffered: In this case, actual I/O takes places when the standard I/O buffer is filled. Files residing on the 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. (完全缓存:在这种情况下,时间的I/O发生在标准I/O缓存被填充时。驻留在磁盘上的文件通常是标准I / O库完全缓冲的。当标准I/O函数第一次调用malloc时获得的缓存在流中执行。)
Line buffered: In this case, the standard I/O library performs I/O when a newline character is encountered on input or output. This allows us to output a sigle character a time, knowing that actual I/O will take palce only when we finish writing each line. Line buffering is typically used on a stream when it refers to a terminal: standard input and standard output, for example. (行缓存:在这种情况下,遇到输入或输出一个换行符时,标准库执行I/O. 这样我们可以一次只输出一个字符。只有在完成整行的写操作时,实际的I/O才会执行。)
Unbuffered: The standard I/O library does not buffer the characters. If we write 15 character with the standard I/O fputs function, for example, we expect these 15 characters to be output as soon as possibly, propably with the write function. (无缓存:标准库不缓存字符。例如我们用fputs函数写15个字符,我们想要这十五个字符尽快的输出,可以使用write函数。)
#include <stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
Returns: 0 if OK, nonzero on error.
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. (这些函数必须在流打开后被调用(很明显,因为每个函数都需要一个有效的文件指针作为它的第一个参数),但是在对流有任何操作之前。)
With setbuf, we can turn buffering on or off.(使用setbuf函数,我们可以打开或者关闭缓存。)
To enable buffering, buf must point to a buffer of length BUFSIZ, a constant defined in <stdio.h>. (打开缓存,buf必须执行一个长度为BUFSIZ的buffer,它在<stdio.h>头文件中定义的常量。)
To disable buffering, we set buf to NULL. (关闭缓存,设置buf为NULL。)
With setvbuf, we specify exactly which type of buffering we want. This is done with the mode argument: _IOFBF, _IOLBF,_IONBU. (使用setvbuf,我们可以明确指定我们想要的缓存类型。这通过mode参数实现:_IOFBF, _IOLBF,_IONBU。)
If we specify an unbuffered stream, the buf and size arguments are ignored. (如果我们指定一个无缓存的流,buf和size参数被忽略。)
If we specify fully buffered or line buffered, buf and size can optionally specify a buffer and its size. (如果我们指定完全缓存或者行缓存,buf和size可选的指定一个buffer和它的大小。)
If the stream is buffered and buf is NULL, the standard I/O library will automatically allocate its own buffer of the appropriate size for the stream. (如果stream是缓存的并且buf是NULL, 标准的I/O库会为流自动的分配它的buffer和一个适当的大小。)
By appropriate size, we mean the value specified by the constant BUFSIZ. (适当的大小是说BUFSIZ常量的值。)
Be aware that if we allocate a standard I/O buffer as an automatic variable within a function, we have to close the stream before returning from the function. (如果我们buffer在一个函数中为自动的变量,我们必须在函数返回之前关闭流。)
In general, we should let the system choose the buffer size and automatically allocate the buffer. When we do this, the standard I/O library automantically release the buffer when we close the stream. (通常,我们应该让系统选择buffer的大小和自动的分配buffer。这时,当我们关闭stream时,标准库会自动释放buffer。)
#include <stdio.h>
int fflush(FILE *fp);
Returns: 0 if OK, EOF on error.
This function causes any unwritten data for the stream to be passed to the kernel. (这个函数把流的所有未写入的数据传递给kernel。)
As a special case, if fp is NULL, this function causes all output streams to be flushed. (作为特殊情况,如果fp是NULL,这个函数会把所有输出流刷新。)
5.5 Opening a Stream (打开流)
#include <stdio.h>
FILE *fopen(const chat *restrict pathname, const char *restrict type);
FILE *freopen(const char *restrict pathname, const char *restrict type, FILE *restrict fp);
FILE *fdopen(int filedes, const char *type);
All three return: file pointer if OK, NULL on error
The fopen function opens a specified file. (fopen函数打开一个指定的文件。)
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. (freopen函数使用指定的流打开一个指定的文件,如果它已经打开拉,首先关闭它。如果流之前已经有值拉,freopen首先清楚它。这个函数通常用于打开一个指定的文件使用预先定义的流:标准输入,标准输出,标准错误。)
The fdopen function takes an existing file descriptor, which we could obtain from the open,dup,dup2,fcntl,pipe,socket,socketpair, or assept 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. (fdopen函数使用一个存在的文件描述符,它可以来自open,dup,dup2,fcntl,pipe,socket,socketpair, 或者 assept函数,并且关联一个标准流。这个函数通常使用那些创建pipes和网络通信频道的函数返回的描述符。)
By default, the stream that is opened is fully buffered, unless it refers to a terminal device, in which case it is line buffered. (打开流默认是完全缓存的,除非它指向一个终端设备才会是行缓存。)
#include <stdio.h>
int fclose(FILE *fp);
Returns: 0 if Ok, EOF on error.
5.6 Reading and Writing a Stream. (读和写Stream)
Character-at-a-time I/O: We can read or write one character at a time, with the standard I/O functions handing all the buffering, if the stream is buffered. (一次一个字节:如果缓存流,我们可以使用标准I/O函数处理缓存,每次可以读或写一个字节。)
Line-at-a-time I/O: If we want to read or write a line at a time, we use fgets and fputs. (使用fgets 和 fputs可以每次读取或写入一行。)
Direct I/O: This type of I/O is supported by the fread and fwrite functions. These two funcitons are often used for binary files where we read or write a structure with each operation. (直接的I/O: fread 和 fwrite 支持这种类型的I/O。这两个函数通常用于二进制文件读取或写入一个结构体。)
Input Functions (输入函数)
#include <stdio.h>
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
All three return: next character if OK, EOF on end of file or error.
The function getchar is defined to be eqivalent to getc(stdin). (getchar函数=getc(stdin))
getc can be implemented as a macro, whereas fgetc cannot be implemented as a macro. (getc 可以实现被实现为一个宏, 然而fgetc却不能。)
1.The argument to getc should not be an expression with side effects. (getc的参数不能是有副作用的表达式。)
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. (由于fgetc确实是一个函数(不是宏),因此我们可以取它的地址。这样我们可以通过传递它的地址作为另一个函数的参数。)
3.Calls to fgetc probably take longer than calls to getc, as it usually takes more time to call a function. (调用fgetc的时间要长于getc,因为它通常需要更多的时间来调用一个函数)
These three functions return the next character as an unsigned char converted to an int. (这三个函数返回下一个字符(无符合的char转变成int)。)
#include <stdio.h>
int ferror(FILE *fp);
int feof(FILE *fp);
Both returns: nonzero(true) if condition is true. 0 (false) otherwise.
void clearerr(FILE *fp);
#include <stdio.h>
int ungetc(int c, FILE *fp);
After reading from a stream, we can push back character by calling ungetc. (从流中读之后,我们可以通过调用ungetc推回一个字符。)
The character that are pushed back are returned by subsequent reads on the stream in reverse order of their pushing. (这些被推回的字符随后会以相反的顺序从流中读取到。)
The character that we push back does not have to be the same character that was read. (推回的字符不必和之前读取的相同。)
We are not able to push back EOF. But when we've reached the end of the file, we can push back a character. (我们不能推回一个EOF,但是当我们到达文件的结尾时,我们可以推回一个字符。)
Output Functions (输出函数)
#include <stdio.h>
int putc(int c, FILE *fp);
int fputc(int c, FILE *fp);
int putchar(int c);
All three return: c if OK, EOF on error.
putchar is equivalent to putc(c, stdout), and putc can be implemented as a macro, whereas fputc cannot be implemented as a macro. (putchar=putc(c, stdout), 并且可以被实现为一个宏,fputc则不能。)
5.7 Line-at-a-Time I/O (一次一行的I/O)
#include <stdio.h>
char *fgets(char *restrict buf, int n, FILE *restrict fp);
char *gets(char *buf);
Both return: buf if OK, NULL on end of file or error
The gets function reads from standard input, whereas fgets reads from the specified stream. (gets 函数从标准输入读取,fgets从指定的流读取。)
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. (使用fgets,我们必须指定buffer的大小n,这个函数可以读取换行符,但最多读取不超过n-1个字符到buffer。)
#include <stdio.h>
int fputs(const char *restrict str, FILE *restrict fp);
int puts(const char *str);
Both return: non-negative value if Ok, EOF on error.
The function fputs writes the null-terminated string to the specified stream. The null byte at the end is not written. (fputs函数向指定的流中写null结尾的字符串,但null字节不会写入。)
Usually, this is the case---the last non-null character is a newline-- but it's not required. (通常,最后一个不是null的自己是换行符,但不是必须的。)
The puts function writes the null-terminated string to the standard output, without writing the bull byte. But puts then writes a newline character to the standard output. (puts函数想标准输出写null结尾的字符串,不写null字节。但是puts函数最后会想标准输出写入一个换行符。)
(完)