标准输入、标准输出和标准错误
这3个标准I/O流通过预定义文件指针stdin、stdout和stderr引用。和文 件 描 述 符 STDIN_FILENO 、 STDOUT_FILENO 和STDERR_FILENO作用的相同。 但应区分文件流与文件描述符前者用于标准IO,后者用于Unix系统IO(无缓冲IO)。
打开流函数
fopen, fdopen, freopen
FILE *fopen(const char *restrict pathname, const char *restrict mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *restrict pathname, const char *restrict mode, FILE *restrict stream);
参数
const char *restrict pathname
:指向要打开文件的路径名字符串(仅对fopen()
和freopen()
有效)。const char *mode
:指定打开模式的字符串,可以是以下几种之一:"r"
:只读方式打开文本文件。"r+"
:读写方式打开文件。"w"
:只写方式打开文件,若文件存在则截断为零长度;否则创建新文件。"w+"
:读写方式打开文件,若文件存在则截断;否则创建新文件。"a"
:追加模式,写入数据总是在文件末尾进行。"a+"
:可读可追加模式,输出始终在文件末尾进行。- 可在上述模式后加上
'b'
表示二进制模式(在 POSIX 系统中无实际影响),或使用其他 glibc 扩展标志如e
、x
等。
int fd
:已打开的文件描述符(仅对fdopen()
有效)。FILE *restrict stream
:指向要被重新打开的流(仅对freopen()
有效)。
返回值
成功时返回指向 FILE
结构的指针;失败时返回 NULL
并设置 errno
来指示错误类型。
详细说明
- 对于
fopen()
,创建的新文件权限默认为0666
,受进程的umask
影响。 - 在读写混合操作时,应使用
fseek()
或fsetpos()
进行定位以符合 ANSI C 规范。 a
和a+
模式下所有写操作都会自动定位到文件末尾。- 不同模式对应不同的底层
open(2)
标志,如下表所示:
fopen() mode | open() flags |
---|---|
r | O_RDONLY |
w | O_WRONLY O_CREAT O_TRUNC |
a | O_WRONLY O_CREAT O_APPEND |
r+ | O_RDWR |
w+ | O_RDWR O_CREAT O_TRUNC |
a+ | O_RDWR O_CREAT O_APPEND |
读取函数
fgetc
int fgetc(FILE *stream);
作用fgetc
用于从指定的文件流中读取下一个字符,并将其作为 unsigned char
转换为 int
返回。如果遇到文件结束或发生错误,则返回 EOF
。
参数
FILE *stream
:指向要读取的文件流的指针。
返回值
- 成功时返回读取到的字符(转换为
int
)。 - 如果到达文件末尾或发生错误,则返回
EOF
。
getc
int getc(FILE *stream);
作用getc
与 fgetc
功能相同,但可能被实现为宏,并且可能会多次计算 stream
参数。
参数
FILE *stream
:指向要读取的文件流的指针。
返回值
- 成功时返回读取到的字符(转换为
int
)。 - 如果到达文件末尾或发生错误,则返回
EOF
。
getchar
int getchar(void);
作用getchar
等价于 getc(stdin)
,即从标准输入流中读取一个字符。
返回值
- 成功时返回读取到的字符(转换为
int
)。 - 如果到达文件末尾或发生错误,则返回
EOF
。
fgets
char *fgets(char s[restrict .size], int size, FILE *restrict stream);
作用fgets
最多从指定流中读取 size - 1
个字符,并将其存储到缓冲区 s
中。读取会在遇到换行符 \n
或文件结束符时停止。如果读到了换行符,它也会被存储到缓冲区中。在字符串末尾会自动添加空字符 \0
。
参数
char *s
:用于存储读取数据的缓冲区。int size
:缓冲区大小,最多读取size - 1
个字符。FILE *stream
:指向要读取的文件流的指针。
返回值
- 成功时返回指向
s
的指针。 - 如果读取过程中出现错误或未读取任何字符就遇到文件结束,则返回
NULL
。
ungetc
int ungetc(int c, FILE *stream);
作用ungetc
将字符 c
(转换为 unsigned char
)压回到指定的文件流中,以便后续读取操作可以重新获取该字符。压回的字符将以相反顺序返回;只能保证一次压回有效。
参数
int c
:要压回的字符。FILE *stream
:目标文件流。
返回值
- 成功时返回压回的字符
c
。 - 失败时返回
EOF
。
fputc
int fputc(int c, FILE *stream);
作用 fputc() 将字符 c(被转换为 unsigned char)写入到指定的流 stream 中。
参数
int c
:要写入的字符。FILE *stream
:指向目标文件流的指针。
返回值
- 成功时返回写入的字符(作为 unsigned char 转换为 int)。
- 失败时返回 EOF,并设置 errno 指示错误类型。
gets
[[deprecated]] char *gets(char *s);
作用gets()
用于从标准输入 (stdin
) 读取一行字符串,直到遇到换行符或文件结束符 (EOF)。它会将读取的内容存储到由参数 s
指向的缓冲区中,并在末尾添加空字符 ('\0'
) 来终止字符串。注意:此函数极其不安全,已被弃用,永远不应使用。
参数
char *s
:指向用于存放读取字符串的缓冲区指针。
返回值
- 成功时返回指向缓冲区
s
的指针。 - 如果发生错误或者在未读取任何字符时遇到文件结束,则返回
NULL
。 - 由于没有进行缓冲区溢出检查,程序可能因缓冲区溢出而崩溃或被恶意利用,因此即使“成功”也可能无法保证函数正常返回。
写入函数
putc
int putc(int c, FILE *stream);
作用 putc() 与 fputc() 功能相同,但可能被实现为宏,并且可能会多次求值 stream 参数。
参数
int c
:要写入的字符。FILE *stream
:指向目标文件流的指针。
返回值
- 成功时返回写入的字符(作为 unsigned char 转换为 int)。
- 失败时返回 EOF,并设置 errno 指示错误类型。
putchar
int putchar(int c);
作用 putchar(c) 等价于 putc(c, stdout),即将字符 c 输出到标准输出流 stdout。
参数
int c
:要输出的字符。
返回值
- 成功时返回写入的字符(作为 unsigned char 转换为 int)。
- 失败时返回 EOF,并设置 errno 指示错误类型。
fputs
int fputs(const char *restrict s, FILE *restrict stream);
作用 fputs() 将字符串 s 写入到指定的流 stream 中,不包括其终止空字符 ‘\0’。
参数
const char *s
:要写入的字符串。FILE *stream
:指向目标文件流的指针。
返回值
- 成功时返回一个非负数。
- 失败时返回 EOF,并设置 errno 指示错误类型。
puts
int puts(const char *s);
作用 puts() 将字符串 s 输出到标准输出流 stdout,并在末尾添加一个换行符。
参数
const char *s
:要输出的字符串。
返回值
- 成功时返回一个非负数。
- 失败时返回 EOF,并设置 errno 指示错误类型。
二进制IO
fread
size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream);
作用fread()
用于从指定的文件流中读取数据。它会读取 nmemb
个数据项,每个数据项的大小为 size
字节,并将这些数据存储到 ptr
指向的内存位置。
与之相对应的是 fwrite()
,用于将数据写入文件流。
这两个函数适用于二进制数据的读写操作。
参数
void *restrict ptr
:指向用于存放读取数据的缓冲区指针。size_t size
:每个数据项的大小(以字节为单位)。size_t nmemb
:要读取的数据项数量。FILE *restrict stream
:指向已打开的文件流结构体指针。
返回值
- 成功时返回实际读取或写入的数据项个数(即:传输的字节数等于
size * 返回值
)。 - 如果在读取过程中遇到文件结束或者发生错误,则返回值会小于请求的项数(或为0)。
- 文件位置指示器会随着成功读写的字节数向前推进。
fread()
不区分“文件结束”和“出错”,调用者必须使用feof(3)
和ferror(3)
来判断具体原因。
fwrite
size_t fwrite(const void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream);
作用
fwrite()
用于将二进制数据写入指定的文件流。它会从 ptr
指向的内存区域中取出 nmemb
个数据项,每个数据项的大小为 size
字节,并写入到 stream
流中。该函数常用于写入结构体或原始字节数据,是标准 I/O 库中进行二进制输出的重要函数。
参数
const void *restrict ptr
:指向要写入的数据所在的缓冲区。size_t size
:每个数据项的大小(以字节为单位)。size_t nmemb
:要写入的数据项数量。FILE *restrict stream
:指向已打开的文件流,必须是以可写模式打开。
返回值
- 成功时返回实际成功写入的数据项个数(即:写入的字节数 /
size
)。只有当size
为 1 时,返回值才等于实际写入的字节数。 - 如果在写入过程中出现错误,则返回值可能小于
nmemb
,甚至为 0。 - 文件的位置指示器会根据实际写入的字节数向前推进。
流的定位
ftell
这个函数常与 fseek
和 rewind
一起使用,用于在文件流中定位或者记录当前读写位置。例如,在读取或写入前记录当前位置,处理完后再恢复位置。
long ftell(FILE *stream);
作用ftell
函数用于获取指定文件流(stream)的当前文件位置指示器的值。这个值表示当前文件指针距离文件起始位置的字节数。
参数
FILE *stream
:指向一个已经打开的文件流。
返回值
- 成功时,返回当前文件位置指示器的值(以字节为单位)。
- 失败时,返回 -1,并设置
errno
指示具体的错误原因。
ftello
off_t ftello(FILE *stream);
作用ftello
函数用于获取指定文件流的当前文件位置指示器的值。它是 ftell(3)
函数的扩展版本,返回值类型为 off_t
而非 long
,以便在支持大文件的系统上处理大于 32 位的文件偏移量。
参数
FILE *stream
:指向已打开文件流的指针。
返回值
- 成功时,返回当前文件位置指示器的值(类型为
off_t
)。 - 失败时,返回
-1
,并设置errno
表示错误类型。
fseek
int fseek(FILE *stream, long offset, int whence);
作用
fseek 用于设置流(stream)的文件位置指示器。新的位置以字节为单位,通过将 offset 字节加到 whence 指定的位置上来确定。如果 whence 设置为 SEEK_SET、SEEK_CUR 或 SEEK_END,则 offset 分别相对于文件开头、当前位置指示器或文件末尾。 成功调用 fseek
会清除流的文件结束指示器 撤销同一流上 ungetc
函数的任何影响。ungetc
实际上只是修改了缓冲区或者内部状态,让下一个读取能重新获得那个字符。如果这时候你调用了 fseek
并且成功移动了文件位置,那么 之前“退回去”的那个字符将不再被读取。
参数
FILE *stream
:指向要重新定位的流。long offset
:相对于 whence 的偏移量(单位为字节)。int whence
:定位的基准位置,可取以下值:SEEK_SET
:从文件开头开始计算偏移。SEEK_CUR
:从当前文件位置开始计算偏移。SEEK_END
:从文件末尾开始计算偏移。
返回值
- 成功时返回 0。
- 失败时返回 -1,并设置 errno 指示错误类型。
rewind
void rewind(FILE *stream);
作用rewind
函数用于将指定文件流的位置指示器重新定位到文件的开头。它等价于调用:
(void) fseek(stream, 0L, SEEK_SET)
但还有一个重要的区别:rewind
函数还会清除文件流的错误指示器(error indicator),而fseek
不会。
参数
FILE *stream
:指向要重定位的文件流的指针。
返回值
rewind
函数没有返回值。
fgetpos
int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
作用fgetpos()
函数用于获取指定文件流的当前文件位置指示器的值,并将其保存到 pos
指向的对象中。该函数提供了一种可移植的方式记录文件中的当前位置,尤其在一些非 UNIX 系统上,对于文本流的定位操作可能是唯一的方法。
参数
FILE *restrict stream
:指向要操作的文件流。fpos_t *restrict pos
:指向用于保存当前位置的fpos_t
类型对象的指针。
返回值
- 成功时返回
0
。 - 失败时返回非零值,并设置
errno
以指示错误类型。
fsetpos
int fsetpos(FILE *stream, const fpos_t *pos);
作用
将 stream
指向的文件流的位置指示器设置为 pos
所指向的位置(该位置通常由 fgetpos()
获得)。
参数
FILE *stream
:指向文件流。const fpos_t *pos
:指向之前由fgetpos()
保存的位置。
返回值
- 成功时返回
0
。 - 失败时返回非零值,并设置
errno
。