Linux学习-应用软件编程(fread/fwrite,流定义相关接口)

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 charargv[])
    {
    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 charargv[])
    {
    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;       // 目标设备的位平面数,必须为1
    short    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);

}
相关推荐
西岸行者7 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意7 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码7 天前
嵌入式学习路线
学习
毛小茛7 天前
计算机系统概论——校验码
学习
babe小鑫7 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms7 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下7 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。7 天前
2026.2.25监控学习
学习
im_AMBER7 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J7 天前
从“Hello World“ 开始 C++
c语言·c++·学习