接着之前的内容,我整理一下fwrite之后的几个关键函数。
fwrite
这个函数用来往文件里写数据,按"元素"来写。
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
四个参数:ptr是数据首地址,size是每个元素多少字节,nmemb是写几个元素,stream是文件流指针。返回实际写入的元素个数,失败时小于nmemb。
举个例子,写一个整型数组:
int arr[5] = {1, 2, 3, 4, 5};
FILE *fp = fopen("data.bin", "w");
fwrite(arr, sizeof(int), 5, fp);
fclose(fp);
fread
和fwrite对应,从文件里读数据。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数含义类似,ptr是存数据的地方。返回实际读到的元素个数,文件里不足一个元素时返回0。
读刚才的文件:
int buf[5] = {0};
FILE *fp = fopen("data.bin", "r");
fread(buf, sizeof(int), 5, fp);
fclose(fp);
fread和fwrite可以操作二进制文件,这是它们比fgets/fputs强的地方。
流定位函数
读写文件时,文件流有一个当前位置指针。三个函数用来控制它。
fseek:移动位置指针
int fseek(FILE *stream, long offset, int whence);
whence有三个取值:SEEK_SET(文件开头)、SEEK_CUR(当前位置)、SEEK_END(文件末尾)。offset是偏移字节数。
ftell:获取当前位置到文件开头的偏移量
long ftell(FILE *stream);
rewind:把位置指针复位到文件开头
void rewind(FILE *stream);
这三个配合可以求文件大小:
fseek(fp, 0, SEEK_END);
long len = ftell(fp);
rewind(fp);
另外,用fseek还能创建空洞文件,提前抢占磁盘空间。
时间相关函数
最后是几个时间函数,处理文件时间戳或者写日志时经常用到。
time:获取从1970年1月1日00:00:00到现在的秒数
#include <time.h>
time_t time(time_t *tloc);
ctime:把秒数转成字符串形式的时间
char *ctime(const time_t *timep);
localtime:把秒数转成日历时间,存在struct tm结构体里
struct tm *localtime(const time_t *timep);
struct tm的字段:
struct tm {
int tm_sec; /* 秒 0-60 */
int tm_min; /* 分 0-59 */
int tm_hour; /* 时 0-23 */
int tm_mday; /* 日 1-31 */
int tm_mon; /* 月 0-11 */
int tm_year; /* 年 – 1900 */
int tm_wday; /* 星期 0-6, 周日=0 */
int tm_yday; /* 一年中第几天 0-365 */
int tm_isdst; /* 夏令时 */
};
用的时候注意,tm_mon是从0开始的,tm_year要加1900才是实际年份。
简单用法:
time_t t = time(NULL);
struct tm *lt = localtime(&t);
printf("%d-%02d-%02d %02d:%02d:%02d\\n",
lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday,
lt->tm_hour, lt->tm_min, lt->tm_sec);




