7 文件操作(C标准库)
在开发时,遇到不熟悉的库函数或系统调用,要善用man手册
函数 | 作用 |
---|---|
fopen | 打开或创建文件,返回相应的文件流。 FILE *fopen(const char *pathname, const char *mode); pathname参数用于指定要打开或创建的文件名。mode参数用于指定文件的打开方式,注意该参数是一个字符串,输入时需要带双引号 |
fread | 从文件流中读取数据 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 返回值为成功读取的项数 |
fwrite | 把数据写入到文件流 size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream); 返回值为成功写入的项数 |
fclose | 关闭指定的文件流,关闭时它会把尚未写到文件的内容都写出 int fclose(FILE *stream) |
fflush | 把尚未写到文件的内容立即写出。常用于确保前面操作的数据被写 入到磁盘上。fclose函数本身也包含了fflush的操作 int fflush(FILE *stream); |
fseek | fseek函数用于设置下一次读写函数操作的位置 int fseek(FILE *stream, long offset, int whence);offset参数用于指定位置,whence参数则定义了offset的意义,whence的可取值如下: |
SEEK_SET:offset是一个绝对位置。 | |
SEEK_END:offset是以文件尾为参考点的相对位置。 | |
SEEK_CUR:offset是以当前位置为参考点的相对位置。 |
既然C标准库和系统调用都能够操作文件,那么应该选择哪种操作呢?考虑的因素如下:
-
使用系统调用会影响系统的性能。执行系统调用时,Linux需要从用户态切换至内核态,执行完毕再返回用户代码,所以减少系统调用能减少这方面的开销。如库函数写入数据的文件操作fwrite最后也是执行了write系统调用,如果是写少量数据的话,直接执行write可能会更高效,但如果是频繁的写入操作,由于fwrite的缓冲区可以减少调用write的次数,这种情况下使用fwrite能更节省时间。
-
硬件本身会限制系统调用本身每次读写数据块的大小。 如针对某种存储设备的write函数每次可能必须写4kB的数据,那么当要写入的实际数据小于4kB时, write也只能按4kB写入,浪费了部分空间,而带缓冲区的fwrite函数面对这种情况, 会尽量在满足数据长度要求时才执行系统调用,减少空间开销。
-
也正是由于库函数带缓冲区,使得我们无法清楚地知道它何时才会真正地把内容写入到硬件上,所以在需要对硬件进行确定的控制时,我们更倾向于执行系统调用。