6.文件位置
ftell: 返回当前的文件位置指示值
fgetpos: 获取文件位置指示器
fseek: 将文件位置指示符移动到文件中的指定位置
fsetpos: 将文件位置指示器移动到文件中的指定位置
rewind: 将文件位置指示器移动到文件首
long ftell( FILE *stream );
返回流 stream 的文件位置指示器。
若流以二进制模式打开,则由此函数获得的值是从文件开始的字节数。
若流以文本模式打开,则由此函数返回的值未指定,且仅若作为fseek()的输入才有意义。
参数
stream: 要检验的文件流
返回值
成功时为文件位置指示器,若失败发生则为-1L。失败时,设errno对象为实现定义的正值
int fgetpos( FILE *stream, fpos_t *pos );
获得文件流 stream 的文件位置指示器和当前分析状态(若存在),并将它们存储于pos所指向的对象。存储的值仅在作为fsetpos的输入的情况有意义。
参数
stream要检验的文件流
pos指向要存储文件位置指示器到的fpos_t对象的指针
返回值
成功为0,否则为非0值
int fseek( FILE *stream, long offset, int origin );
设置文件流 stream 的文件位置指示器为 offset 所指向的值。
1)若 stream 以二进制模式打开,则新位置准确地是文件起始后(若 origin 为 SEEK_SET)或当前文件位置后(若 origin 为 SEEK_CUR),或文件结尾后(若 origin 为 SEEK_END)的 offset 字节。不要求二进制流支持 SEEK_END,尤其是是否输出附加的空字节。
2)若 stream 以文本模式打开,则仅有的受支持 offset 值为零(可用于任何 origin)和先前在关联到同一个文件的流上对 ftell 的调用的返回值(仅可用于 SEEK_SET 的 origin )。
3)若 stream 为宽面向,则一同应用对文本和二进制流的限制(允许 ftell 的结果与 SEEK_SET 一同使用,并允许零 offset 以 SEEK_SET 和 SEEK_CUR 但非 SEEK_END 为基准)。除了更改文件位置指示器,fseek 还撤销 ungetc 的效果并清除文件尾状态,若可应用。若发生读或写错误,则设置流的错误指示器(ferror)而不影响文件位置。
参数
stream: 要修改的文件流
offset: 相对 origin 迁移的字符数
origin: offset 所加上的位置。它能拥有下列值之一:SEEK_SET、SEEK_CUR、SEEK_END
返回值
成功为0,否则为非0值
int fsetpos(FILE *stream, const fpos_t *pos);
按照pos所指向的值,设置文件流stream的文件位置指示器和多字节分析状态(若存在)。除了建立新的分析状态和位置,调用此函数还会撤销ungetc的效果,并若设置了文件尾状态则清除之。若读或写出现错误,则设置流的错误指示器(ferror)。
参数
stream要修改的文件流
pos指向fpos_t对象的指针,用作文件位置指示器的新值
返回值
成功时为0,否则为非零值。
void rewind( FILE *stream);
移动文件位置指示器到给定文件流的起始。函数等价于fseek(stream, 0, SEEK_SET),除了它清除文件尾和错误指示器。此函数丢弃任何来自先前对ungetc调用的效果。
参数
stream要修改的文件流
返回值(无)
7.错误处理
clearerr 清除错误
feof 检查文件结尾
ferror 检查文件错误
perror 显示对应当前错误的字符串到stderr
void clearerr( FILE *stream );
重置给定文件流的错误标志和EOF指示器。
参数
stream: 要重置错误标志的文件流
返回值(无)
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
int main(void)
{
FILE* tmpf = tmpfile();
fputs("abcde\n", tmpf);
rewind(tmpf);
int ch;
while((ch=fgetc(tmpf))!=EOF)
printf("%c", ch);
assert(feof(tmpf)); // 此循环期待以 eof 终止
puts("End of file reached");
clearerr(tmpf); // 清除 eof
if (feof(tmpf))
puts("EOF indicator set");
else
puts("EOF indicator cleared\n");
}
int feof(FILE *stream);
检查是否已抵达给定文件流的结尾。
参数
stream 要检验的文件流
返回值
若已抵达流尾则为非零值,否则为0
注意
此函数仅报告最近一次 I/O 操作所报告的流状态,而不检验关联的数据源。例如,若最近一次 I/O 是抵达文件最后字节的 fgetc,则 feof 返回零。下个 fgetc 失败并更改流状态为文件尾。然后 feof 才返回非零。
典型用法中,输入流处理在任何错误时停止;而 feof 和 ferror 用于区别不同错误条件。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE* fp = fopen("test.txt", "r");
if (!fp) {
perror("File opening failed");
return EXIT_FAILURE;
}
int c;
while ((c = fgetc(fp)) != EOF) {
putchar(c);
}
if (ferror(fp))
puts("I/O error when reading");
else if (feof(fp))
puts("End of file reached successfully");
fclose(fp);
}
int ferror(FILE *stream);
检查给定文件流的错误。
参数
stream 要检查的文件流
返回值
若文件流已出现错误则为非零值,否则为0
void perror(const char *s);
打印当前存储于系统变量 errno 的错误码到 stderr。
通过连接下列组分构成描述:
● s 所指向的空终止字节字符串的内容后随“: ”(除非 s 为空指针或 s 所指向字符为空字符)
● 实现定义的,描述存储于 errno 的错误码的错误消息字符串
● 后随换行符“\n”
错误消息字符串等同于 strerror(errno)的结果。
参数
s 指向带解释消息的空终止字符串的指针
返回值 无
8.文件操作
remove 删除文件
rename 重命名文件
tmpfile 返回指向临时文件的指针
tmpfile_s (c11)
int remove(const char *fname)
删除fname所指向的字符串所标识的文件。若文件为当前进程或另一进程打开,则此函数行为是实现定义的。具体而言,POSIX系统解链接文件名,到最后一个运行的进程关闭该文件为止,即使这是最后一个到文件的硬链接也不回收文件系统空间。Windows不允许删除该文件。
参数
fname 指向空终止字符串的指针,字符串含标识待删除文件的路径
返回值
成功时为0,错误时为非零值。
注意 POSIX 指定此函数行为的许多额外细节。
#include<stdio.h>
int main(void)
{
FILE* fp = fopen("file1.txt", "w");
if(!fp) {
perror("file1.txt");
return 1;
}
puts("Created file1.txt");
fclose(fp);
int rc = remove("file1.txt");
if(rc) {
perror("remove");
return 1;
}
puts("Removed file1.txt");
fp = fopen("file1.txt", "r");
if(!fp)
perror("Opening removed file failed");
}
rc = remove("file1.txt");
if(rc)
perror("Double-remove failed");
int rename(const char *old_filename, const char *new_filename);
更改文件的文件名。该文件以old_filename所指向的字符串标识。新文件名以new_filename所指向的字符串标识。若new_filename存在,则行为是实现定义的。
参数
old_filename 指向包含标识要重命名的文件的路径的空终止字符串的指针
new_filename 指向包含文件新路径的空终止字符串的指针
返回值
成功时为0,失败时为非零值。
#include<stdio.h>
int main(void)
{
FILE* fp = fopen("from.txt", "w");
if(!fp) {
perror("from.txt");
return 1;
}
fputc('a', fp);
fclose(fp);
int rc = rename("from.txt", "to.txt");
if(rc) {
perror("rename");
return 1;
}
fp = fopen("to.txt", "r");
if(!fp) {
perror("to.txt");
return 1;
}
printf("%c\n", fgetc(fp));
fclose(fp);
}
9.无格式输入/输出
fgetc getc 从文件流获取一个字符
fgets 从文件流获取一个字符串
fputc putc 将一个字符写入文件流
fputs 将一个字符串写入文件流
getchar 从 stdin 读取一个字符
gets(C11 中移除)
gets_s 从 stdin 读取一个字符串
putchar 将一个字符写入 stdout
puts 将一个字符串写入 stdout
ungetc 将一个字符送回文件流
int fgetc( FILE *stream ); int getc( FILE *stream );
从给定的输入流读取下一个字符。getc()可以实现为宏。
参数
stream 读取字符的来源
返回值
成功时为获得的字符,失败时为EOF。
若文件尾条件导致失败,则另外设置stream上的文件尾指示器(见feof()。若某些其他错误导致失败,则设置stream上的错误指示器(见ferror()。
int fputs( const char *str, FILE *stream );
int fputs( const char *restrict str,FILE *restrict stream );
将以NULL结尾的字符串str的每个字符写入到输出流stream,如同通过重复执行fputc。不将str的空字符写入
参数
str 要写入的空终止字符串
stream 输出流
返回值
成功时,返回非负值。 失败时,返回EOF并设置stream上的错误指示器(见rror)。
注意
相关函数puts后附新换行符到输出,而fputs写入不修改的字符串。不同的实现返回不同的非负数:一些返回最后写入的字符,一些返回写入的字符数(或若字符串长于INT_MAX则为该值),一些简单地非负常量,例如零。
int getchar(void);
从 stdin 读取下一个字符。等价于 getc(stdin)。
参数(无)
返回值
成功时为获得的字符,失败时为 EOF。若失败由文件尾条件产生,则另外设置 stdin 上的文件尾指示器(见 feof())。若失败由某些其他错误产生,则设置 stdin 上的错误指示器。
char *gets(char *str); (C11 中移除)
char *gets_s(char *str, rsize_t n); (C11 起)
1)从 stdin 读入 str 所指向的字符数组,直到发现换行符或出现文件尾。在读入数组的最后一个字符后立即写入空字符。换行符被舍弃,但不会存储于缓冲区中。
2)从 stdin 读取字符直到发现换行符或出现文件尾。至多写入 n-1 个字符到 str 所指向的数组,并始终写入空终止字符(除非 str 是空指针)。若发现换行符,则忽略它并且不将它计入写入缓冲区的字符数。
在运行时检测下列错误并调用当前安装的制约处理函数:
● n为零
● n大于 RSIZE_MAX
● str是空指针
● 在存储 n-1 个字符到缓冲区后没有遇到换行符或文件尾。
任何情况下,gets_s 首先结束读取并忽略来自 stdin 的字符,直到换行符、文件尾条件,或在调用制约处理前的读取错误。同所有边界检查函数,gets_s 仅若实现定义 __STDC_LIB_EXT1__ 且用户在包含stdio.h前定义 __STDC_WANT_LIB_EXT1__ 为整数常量 1 才保证可用。
参数
str 要被写入的字符串
n char 数组的最大长度
返回值
成功时为 str,失败时为空指针。若文件尾条件导致了失败,则附加设置 stdin 的文件尾指示器(见 feof() )。若其他某些原因导致了失败,则设置 stdin 的错误指示器。
注解
gets() 函数不进行边界检查,从而此函数对缓冲区溢出攻击极度脆弱。无法安全使用它(除非程序运行的环境限定能出现在 stdin 上的内容)。因此,此函数在 C99 的第三次勘误中被弃用,而在 C11 标准发布时被移除。推荐的替代品是 fgets() 和 gets_s()。绝对不要用 gets()。
int putchar( int ch );
写字符 ch 到 stdout。在内部,字符于写入前被转换为 unsigned char。等价于 fputc( ch , stdout )。
参数
ch 要被写入的字符
返回值
成功时返回写入的字符。失败时返回 EOF 并设置 stdout 上的错误指示器(见 ferror )。
int puts(const char *str);
写入每个来自空终止字符串str的字符及附加换行符'\n'到输出流stdout,如同以重复执行putc写入。
不写入来自str的空终止字符。
参数
str 要写入的字符串
返回值
成功时返回非负值;失败时,返回EOF并设置stdout的错误指示器(见ferror())。
注意
puts函数后附一个换行字符到输出,而fputs不这么做。不同的实现返回不同的非负数:一些返回最后写入的字符,一些返回写入的字符数(或若字符串长于INT_MAX则返回它),一些简单地返回非负常量。在重定向stdout到文件时,导致puts失败的典型原因是用尽了文件系统的空间。
int ungetc( int ch, FILE *stream );
若 ch 不等于 EOF,则推入字符 ch (转译为 unsigned char )到与流 stream 关联的输入缓冲区,方式满足从 stream 的后继读取操作将取得该字符。不修改与流关联的外部设备。
流重寻位操作 fseek、fsetpos 和 rewind 弃去 ungetc 的效果。
若调用 ungetc 多于一次,而无中间读取或重寻位,则可能失败(换言之,保证大小为 1 的回放缓冲区,但任何更大的缓冲区是实现定义的)。若成功进行多次 ungetc ,则读取操作以 ungetc 的逆序取得回放的字符。
若 ch 等于 EOF ,则操作失败而不影响流。
对 ungetc 的成功调用清除文件尾状态标志 feof 。
在二进制流上对 ungetc 的成功调用将流位置指示器减少一(若流位置指示器为零,则行为不确定)。
在文本流上对 ungetc 的成功调用以未指定方式修改流位置指示器,但保证在以读取操作取得所有回放字符后,流位置指示器等于其在 ungetc 之前的值。
参数
ch 要推入输入流缓冲区的字符
stream 要回放字符到的文件流
返回值
成功时返回 ch 。
失败时返回 EOF ,而给定的流保持不变。
注意
实践中,回放缓冲区的大小会在 4k ( Linux 、 MacOS )和 4 ( Solaris )或保证的最小值 1 ( HPUX 、 AIX )间变化。若回放的字符等于存在于外部字符序列中该位置的字符,则回放缓冲区的表观大小可以更大(实现可以简单地自减读取的文件位置指示器,并避免维护回放缓冲区)。