fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能
按块从文件读取数据,从文件中读 nmemb 个、每个 size 字节的元素,存入 ptr 指向的内存。
参数
- ptr :存储读取数据的内存首地址(需提前分配足够空间,如定义数组、用 malloc 申请堆内存 )。
- size :单个元素的字节数(同 fwrite ,需和写入时的 size 一致,否则数据会错位 )。
- nmemb :希望读取的元素个数(尝试读 size * nmemb 字节,实际读多少看文件内容 )。
- stream :文件流指针(通过 fopen 打开,需以可读模式如 "r+" 等打开 )。
返回值
- 成功:返回实际读到的元素个数(等于 nmemb 表示读满;若文件末尾不够 nmemb 个元素,返回实际读到的数量 )。
- 文件末尾:返回 0 (可用来判断是否读完文件 )。
#include<stdio.h>
struct stu
{int id;char name[100];int score;
};
int main(int argc,const char*argv[])
{FILE*fp = fopen("./1.txt","r");if(NULL == fp){printf("fopen error\n");return -1;}struct stu s;struct stu ss[10];size_t cnt = fread(&s,sizeof(struct stu),1,fp);printf("cnt = %ld\n",cnt);printf("%d %s %d\n",s.id,s.name,s.score);cnt = fread(ss,sizeof(struct stu),10,fp);printf("cnt = %ld\n",cnt);for(int i = 0;i < cnt;i++){printf("%d %s %d\n",ss[i].id,ss[i].name,ss[i].score);}fclose(fp);
}
fwrite
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能
按块向文件写入数据,把 ptr 指向的内存数据,以「 size 字节/元素 、共 nmemb 个元素」的形式写入文件。
参数
- ptr :要写入数据的内存首地址(常搭配数组、结构体等,传递 &变量 或数组名)。
- size :单个元素的字节数(如 sizeof(int) 表示 int 类型占 4 字节)。
- nmemb :要写入的元素个数(需和 size 匹配,总写入字节 = size * nmemb )。
- stream :文件流指针(通过 fopen 打开文件获得,需确保以可写模式如 "wb" 、 "a+" 等打开 )。
返回值
- 成功:返回实际写入的元素个数(正常应等于 nmemb ;若磁盘满、权限不足等,可能小于)。
#include<stdio.h>struct stu
{int id;char name[100];int score;
};
int main(int argc,const char*argv[])
{FILE*fp = fopen("./1.txt","w");if(NULL == fp){printf("fopen error\n");return -1;}struct stu ss[5] = {{1,"zahngsan",99},{2,"lisi",90},{3,"wangwu",98},{4,"maliu",67},{5,"wanger",100}};size_t cnt = fwrite(ss,sizeof(struct stu),5,fp);printf("cnt = %ld\n",cnt);fclose(fp);
}
bmp
#pragma pack(1)//bmp文件相关信息
typedef struct tagBITMAPFILEHEADER {short bfType; // 文件类型标志int bfSize; // 文件大小,单位为字节short bfReserved1; // 保留字节short bfReserved2; // 保留字节int bfOffBits; // 数据偏移量,即实际图像数据开始的位置
}Bmp_file_head_t;
//bmp图像信息
typedef struct tagBITMAPINFOHEADER {int biSize; // BITMAPINFOHEADER的大小,单位为字节int biWidth; // 位图的宽度,单位为像素int biHeight; // 位图的高度,单位为像素short biPlanes; // 目标设备的位平面数,必须为1short biBitCount; // 每像素位数(颜色深度)int biCompression; // 图像压缩类型int biSizeImage; // 图像大小,单位为字节int biXPelsPerMeter;// 水平分辨率,单位为像素/米int biYPelsPerMeter;// 垂直分辨率,单位为像素/米int biClrUsed; // 实际使用颜色数int biClrImportant; // 重要颜色数
}Bmp_info_t;
#pragma pack()int get_bmp_head_info(const char *bmpname, Bmp_file_head_t *pheadinfo, Bmp_info_t *pbmpinfo)
{FILE *fp = fopen(bmpname, "r");if (NULL == fp){printf("fopen error\n");return -1;}fread(pheadinfo, sizeof(Bmp_file_head_t), 1, fp);fread(pbmpinfo, sizeof(Bmp_info_t), 1, fp);fclose(fp);return 0;
}int main(int argc, const char *argv[])
{Bmp_file_head_t headinfo;Bmp_info_t bmpinfo;get_bmp_head_info("./3.bmp", &headinfo, &bmpinfo);printf("sizeof(Bmp_file_head_t) = %ld\n", sizeof(Bmp_file_head_t));printf("sizeof(Bmp_info_t) = %ld\n", sizeof(Bmp_info_t));printf("biWidth = %d, biHeight = %d, biBitCount = %d\n", bmpinfo.biWidth, bmpinfo.biHeight, bmpinfo.biBitCount);return 0;
}
流定位相关接口
fseek
int fseek(FILE *stream, long offset, int whence);
功能
实现文件流的重新定位,用于调整文件内部指针的位置,决定后续读写操作从文件的哪个位置开始。
参数
- stream :需要进行定位操作的文件流指针,由 fopen 等函数打开文件后获得。
- offset :偏移量,用于指定相对于 whence 位置移动的字节数,可正(向后移动 )、可负(向前移动 ,但需注意不能越界 )。
- whence :定位的相对基准位置,有以下宏定义可选:
- SEEK_SET :以文件开头为基准进行偏移, offset 为相对于文件开头的偏移字节数。
- SEEK_CUR :以文件当前读写位置为基准进行偏移, offset 是相对于当前位置的偏移量。
- SEEK_END :以文件末尾为基准进行偏移, offset 常搭配负数,实现从末尾往前定位(如 fseek(stream, -10, SEEK_END) 表示定位到文件末尾向前 10 字节处 )。
返回值
- 成功:返回 当前偏移量。
- 失败:返回 -1 ,常见失败情况如偏移量导致越界(如 SEEK_SET 时 offset 为负数 )、文件流异常等。
rewind(fp) ==>fseek(fp,0,SEEK_SET)
ftell
long ftell(FILE *stream);
功能
获取文件流当前位置到文件开头的偏移量,即返回当前文件指针距离文件起始位置的字节数,可用于判断文件大小、辅助 fseek 定位等场景。
返回值
偏移量:byte
练习
#include<stdio.h>
#include<stdlib.h>
struct stu
{int id;char name[100];int score;
};
int main(int argc,const char*argv[])
{FILE*fp = fopen("./1.txt","w+");if(NULL == fp){printf("fopen error\n");return -1;}struct stu ss[5] = {{1,"zahngsan",99},{2,"lisi",90},{3,"wangwu",98},{4,"maliu",67},{5,"wanger",100}};fwrite(ss,sizeof(struct stu),5,fp);fseek(fp,0,SEEK_END);long len = ftell(fp);rewind(fp);FILE*fp1 = fopen("./2.txt","w");if(NULL == fp1){printf("fopen error\n");return -1;}//空洞文件fseek(fp1,len - 1,SEEK_SET);int ret = fputc('\0',fp1);if(EOF == ret){printf("磁盘空间不足\n");return -1;}fseek(fp1,0,SEEK_SET);char *buff = malloc(len);fread(buff,1,len,fp);fwrite(buff,1,len,fp1);free(buff);fclose(fp);fclose(fp1);
}
strtok
char *strtok(char *str, const char *delim);
功能
按分隔符截取字符串,从 str 中逐个提取由 delim 分隔的子串。首次调用需传入待分割的完整字符串 str ,后续调用传入 NULL 即可继续分割剩余部分(内部会维护静态指针记录位置 )。
参数
- str :
- 首次调用:传入待分割的原始字符串(会被函数修改,分割后原字符串会被分隔符替换为 \0 ,用于标记子串结束 )。
- 后续调用:传入 NULL ,函数会基于内部静态指针,继续分割剩余未处理的部分。
- delim :
传入分隔符字符串(如 ",-" 表示逗号、减号都可作为分隔符 ),只要遇到 delim 中任意字符,就会停止当前子串截取。
返回值
- 成功:返回当前截取到的子串首地址(如分割 "a,b,c" ,首次返回 "a" 的地址,后续依次返回 "b" 、 "c" )。
- 失败/结束:返回 NULL (当没有可分割的子串时触发 )。
练习
实现一个单词查询软件: 用户从终端输入一个单词,查找该单词的意思并打印; 若用户输入".quit",则退出该软件。
#include<stdio.h>
#include <string.h>
int main(int argc,const char*argv[])
{FILE*fp = fopen("./dict.txt","r");if(NULL == fp){printf("fopen error\n");return -1;}rewind(fp);char s[1024];printf("输入单词\n");scanf("%s",s);char buff[1024] = {0};if(0 == strcmp(".quit",s)){return 0; }char *p = fgets(buff,sizeof(buff),fp);while(p != NULL){char *b = strtok(buff," ");if(0 == strcmp(b,s)){b = strtok(NULL,"\r");printf("%s%s\n",s,b);break;}p = fgets(buff,sizeof(buff),fp);}if(p == NULL){printf("not find\n");return 0;}fclose(fp);}