文件操作
删除文件
int remove(const char *filename);
remove
函数类似于Unix/Linux命令rm
,接受一个文件名,然后删除其对应的文件。对于大多数文件系统,删除文件仅仅是删除文件索引,并不擦除硬盘内容,所以能在一瞬间完成。
函数执行成功返回0,失败返回非0。
重命名文件
int rename(const char *old, const char *new);
rename
函数类似于Unix/Linux命令mv
,不仅能重命名文件,也能把文件移动到其他目录,因为二者原理是一样的,都是修改目录而不改变文件本身。当old和new对应的文件不在同一个文件系统上时,rename
函数将失败。因为跨文件系统移动文件需要复制文件,和在同一个文件系统内移动文件的原理完全不同。
函数执行成功返回0,失败返回非0。
创建临时文件
FILE *tmpfile(void);
tmpfile
函数会创建并打开一个不重名的临时文件,当文件关闭或者程序退出时,这个文件会自动删除。文件的打开方式为wb+
,对于Unix/Linux,这个临时文件位于/tmp
目录下。
函数执行成功返回临时文件对应的FILE *
指针(即流),失败返回空指针。
打开文件
FILE *fopen(const char * restrict filename,
const char * restrict mode);
fopen
函数打开一个文件并关联到一个新创建的流。函数执行成功返回这个流,失败返回空指针。
mode是文件的打开方式,为一个字符串,函数将依次解析里面的每个字符。
基本的打开方式有r、w、a,他们是互斥的,只能出现一个,必须放在mode字符串的开头。
- r:读取文件。如果文件不存在或没有访问权限,则打开失败。不会截断文件。
- w:写入文件。如果文件不存在则创建文件,如果文件存在则截断文件(除非指定了x)。
- a:追加到文件。如果文件不存在则创建文件,如果文件存在则追加到文件末尾。
此外,还有一些额外的模式限定字符,他们不能独立出现,必须依赖于上面提到的基本打开方式。它们不是互斥的,可按需组合。
- b:以二进制模式打开。没有b则默认是文本模式。
- +:以更新模式打开。既可以读又可以写。
- x:以独占模式打开,只能跟w配合使用。如果文件不存在则创建文件,如果文件存在则打开失败。
以更新模式(+)打开文件时,流既可以进行读操作也可以进行写操作,但同一时刻只能处于读或写的一种状态。不同状态间文件位置指示器和缓冲区是通用的。进行读操作可以把流状态设置为读,进行写操作可以把流状态设置为写。在很多实现里,切换到读状态将刷新写状态的缓冲区。
如果以 a 或 ab 模式打开文件,则会阻止fseek
等函数对文件位置指示器的修改,文件位置指示器永远指向文件末尾,所有输出内容被强制追加到文件末尾。
如果以 a+ 或 ab+ 模式打开文件,则fseek
等函数可以生效,以调整读取时的文件位置。但是一旦进行写入,文件位置指示器就被设置到文件末尾,所有输出内容都会被强制追加到文件末尾。
关闭文件
int fclose(FILE *stream);
fclose
函数关闭一个已打开的文件,并释放与其关联的流。fclose
在关闭文件之前会先刷新缓冲区。
函数执行成功返回0,失败返回EOF。
无论文件是否成功关闭,该流都将与该文件取消关联,释放该流以及自动分配的缓冲区。
当程序正常结束(main函数返回或调用exit
函数)时,所有打开的流都会被关闭,效果同调用fclose
。
流操作
重定向流
FILE *freopen(const char * restrict filename,
const char * restrict mode,
FILE * restrict stream);
freopen
函数关闭并取消关联原文件,然后打开一个新文件并关联到该流。
函数执行成功返回该流,失败返回空指针。
freopen
函数先关闭原文件,原文件是否成功关闭不影响后续操作以及返回值。之后尝试打开指定文件,如果打开失败则返回空指针。如果成功打开并关联到一个新文件,流的错误标志以及EOF标志会被重置。
如果filename是一个空指针,freopen
函数会尝试将流模式更改为mode指定的模式,不会关闭或取消关联原文件。
freopen
主要用于重定向stdin、stdout、stderr,但是更简洁的方法是直接打开文件并赋值给这些指针。
刷新缓冲区
int fflush(FILE *stream);
fflush
函数会刷新给定输出流的缓冲区,包括以写模式、追加模式打开,或者以更新模式打开且处于写状态的流。缓冲区中的内容会立刻写入对应文件中。
函数执行成功返回0,失败返回EOF。
对输入流调用fflush
的行为是未定义的。C标准没有提供刷新输入缓冲区的方法。
如果stream是空指针,那么fflush
会刷新所有的输出流。
设置缓冲区
设置缓冲区应该在流关联到一个文件之后,且进行任何其他操作之前。否则,行为是未定义的。
当流关联到一个文件,在进行任何其他操作之前,缓冲区是未分配的,此时设置缓冲区是安全的,不会造成内容丢失。
setvbuf
int setvbuf(FILE * restrict stream,
char * restrict buf,
int mode, size_t size);
setvbuf
函数将把buf所指的内存区域作为流的缓冲区,size表示缓冲区大小,mode表示缓冲方式。
函数执行成功返回0,失败返回非0。
如果buf是空指针,setvbuf
函数将自动分配给流一个缓冲区,size指定该缓冲区的大小。
mod接受三个预定义的宏:
- _IOFBF:全缓冲
- _IOLBF:行缓冲
- _IONBF:无缓冲
setbuf
void setbuf(FILE * restrict stream,
char * restrict buf);
setbuf
函数与setvbuf
函数功能相近,不过默认把宏 _IOFBF作为缓冲方式,把宏BUFSIZ作为缓冲区大小。如果buf是空指针,把宏 _IONBF作为缓冲方式。
setbuf
函数没有返回值。
文件位置操作
对于支持位置请求的流(比如关联到普通文件的流,而不是关联到终端的流),包含一个文件位置指示器,可以进行文件位置操作。
在很多实现里,设置文件位置指示器将刷新输出缓冲区。
ftell
long int ftell(FILE *stream);
ftell
函数获取文件位置指示器的值,即当前位置距离文件开头的偏移量。从0开始,单位是字节。
函数执行成功返回表示偏移量的整数值,失败返回-1。
fseek
int fseek(FILE *stream, long int offset, int whence);
fseek
函数用来设置文件位置指示器的值。whence表示起点,offset表示距离起点的偏移量。
函数执行成功返回0,失败返回非0。
whence接受三个预定义宏:
- SEEK_SET:文件开头,偏移量为0
- SEEK_CUR:当前位置,即当前文件位置指示器的值
- SEEK_END:文件末尾,在最后一个字节之后
offset的值可以是正数,也可以是负数或0。
如果fseek
函数执行成功,将重置流的EOF标志。
rewind
void rewind(FILE *stream);
rewind
函数将文件位置指示器退回到文件开头。该函数没有返回值。
如果rewind
函数执行成功,将重置流的EOF标志以及错误标志。
fgetpos
int fgetpos(FILE * restrict stream,
fpos_t * restrict pos);
fgetpos
函数将文件位置指示器的值以及宽字符流的解析状态存入pos所指的对象中。
函数执行成功返回0,失败返回非0。
fsetpos
int fsetpos(FILE *stream, const fpos_t *pos);
fsetpos
函数将根据pos所指的对象,设置文件位置指示器的值以及宽字符流的解析状态。
函数执行成功返回0,失败返回非0。
pos所指的对象应该是上次对同一个流调用fgetpos
产生的结果。如果fsetpos
函数执行成功,将重置流的EOF标志。
流状态操作
feof
int feof(FILE *stream);
feof
函数检查流的EOF标志是否被设置。
如果流的EOF标志被设置,返回非0;否则返回0。
ferror
int ferror(FILE *stream);
ferror
函数检查流的错误标志是否被设置。
如果流的错误标志被设置,返回非0;否则返回0。
clearerr
void clearerr(FILE *stream);
clearerr
函数重置流的EOF标志和错误标志。该函数没有返回值。
perror
void perror(const char *s);
perror
函数将错误标志的序号映射成错误消息字符串,并输出到stderr。该函数没有返回值。
错误消息字符串的末尾包含一个换行符。如果s是一个有效的字符串(不是空指针且不指向'\0'
),那么会先输出该字符串的内容,跟着输出一个": "
(冒号和空格),然后输出错误消息字符串的内容。