当前位置: 首页 > news >正文

【学习嵌入式day23-Linux编程-文件IO】

目录

使用fgets和fputs实现文件拷贝

整体思路:

fwrite

fread

使用fread和fwrite完成对图片的拷贝

整体思路:

流的定位

概念:

fseek

ftell

rewind

从终端输入文件名,得到文件的长度

读取BMP图片的宽度和高度

文件IO

概念

系统调用与库函数

文件IO函数接口

函数接口

文件打开

关闭文件描述符

标准IO对应的文件IO的打开方式

文件IO读写

write

read

使用read和write完成对图片的拷贝

文件描述符偏移量的定位

lseek

文件IO与标准IO互相转换的函数

fileno

fdopen

feof

ferror

目录IO

操作方式

函数接口

opendir

closedir

readdir

getcwd:获得当前工作目录的绝对路径

chdir:切换当前的工作路径

递归实现目录的遍历

队列实现目录的广度遍历

时间相关的函数接口

时间类型分类

time_t类型时间

struct tm类型时间

char *字符串类型时间

函数接口

time

localtime:将秒数转换为结构体时间

mktime:将结构体时间转换为time_t类型

ctime将Time_t转换为字符型时间


等价于gets的功能

使用fgets和fputs实现文件拷贝

整体思路:

fgets完成从流中接收一行数据到文件中

fputs完成从文件中写入字符串

  1. 使用fgets从终端接收源文件和目的文件
  2. 打开fopen源文件和目的文件
  3. 使用while(1)循环从源文件读数据fgets,往目的文件写数据fputs
  4. 关闭源文件和目的文件
//使用fgets和fputs实现文件拷贝#include <stdio.h>
#include <errno.h>
#include <string.h>void copy_file_content(char *pdst, char *psrc)
{FILE *fsrc = NULL;FILE *fdst = NULL;char tmpbuff[256] = {0};char *pret = NULL;
//打开两个文件fsrc = fopen(psrc, "r");if(NULL == fsrc){perror("fail to fopen");return;}fdst = fopen(pdst, "w");if(NULL == fdst){perror("fail to fopen");return;}while (1){pret = fgets(tmpbuff, sizeof(tmpbuff), fsrc);if(NULL == pret){break;}fputs(tmpbuff, fdst);}fclose(fsrc);fclose(fdst);return;
}int main(void)
{char srcfile[256] = {0};char dstfile[256] = {0};printf("请输入源文件:\n");//gets(srcfile);//也可以使用fgetsfgets(srcfile, sizeof(srcfile), stdin);srcfile[strlen(srcfile)-1] = '\0';printf("请输入目的文件:\n");//gets(dstfile);//也可以使用fgersfgets(dstfile, sizeof(dstfile), stdin);dstfile[strlen(dstfile)-1] = '\0';copy_file_content(dstfile, srcfile);printf("拷贝完成\n");return 0;
}

fwrite

往文件里写二进制数据

#include <stdio.h>typedef struct student
{char name[32];char sex;int age;int score;
}stu_t;int main(void)
{FILE *fp = NULL;size_t nret = 0;stu_t s = {"zhangsan", 'm', 18, 90};stu_t s1 = {"lisi", 'f', 19, 85};//定义一个结构体数组stu_t stu[3] = {{"wangwu", 'm', 20, 95},{"xiaozhang", 'f', 19, 80},{"xiaowu", 'm', 18, 75},};fp = fopen("a.txt", "w");if(NULL == fp){perror("fail to fopen");return -1;}nret = fwrite(&s, sizeof(s), 1, fp);printf("nret = %ld\n", nret);nret = fwrite(&s1, sizeof(s1), 1, fp);printf("nret = %ld\n", nret);nret = fwrite(stu, sizeof(stu_t), 3, fp);printf("nret = %ld\n", nret);fclose(fp);return 0;
}

Makefile文件

#要生成的文件名
OBJ=a.out#依赖的所有文件
OBJS+=main.c$(OBJ):$(OBJS)gcc $^ -o $@

fread

从文件里读二进制数据

#include <stdio.h>typedef struct student{char name[32];char sex;int age;int score;
}stu_t;int main(void)
{FILE *fp = NULL;stu_t s;stu_t stu[10];size_t nret = 0;int i = 0;fp = fopen("a.txt", "r");if(NULL == fp){perror("fail to fopen");return -1;}//一次读所有的nretnret = fread(stu, sizeof(stu_t), 10, fp);printf("nret = %ld\n", nret);for(i = 0; i < nret; i++){printf("姓名:%s\n", stu[i].name);printf("性别:%c\n", stu[i].sex);printf("年龄:%d\n", stu[i].age);printf("分数:%d\n", stu[i].score);}printf("===============");//一次只读一个nret
/*while(1){nret = fread(&s, sizeof(s), 1, fp);if(0 == nret){break;}printf("nret = %ld\n", nret);printf("姓名:%s\n", s.name);printf("性别:%c\n", s.sex);printf("年龄:%d\n", s.age);printf("分数:%d\n", s.score);}
*/fclose(fp);return 0;
}

使用fread和fwrite完成对图片的拷贝

整体思路:

  1. 使用只读方式,打开原图片( fopen )
  2. 使用读写方式,打开目的图片( fopen )
  3. fread读原图片,参数:每次读一个字节,读4096个对象,循环完成
  4. fwrite写,往目的图片文件里写 所读到的内容。参数:每次读一个字节,读nret(fread的返回值)个对象。
  5. 关闭原图片和目的图片
#include <stdio.h>int main(void)
{FILE *fp_src = NULL;FILE *fp_dst = NULL;
//定义缓存区的大小char tmpbuff[4096] = {0};size_t nret = 0;//只读方式,打开原图片fp_src = fopen("1.png", "r");if(NULL == fp_src){perror("fail to fopen");return -1;}
//读写方式,打开目的图片fp_dst = fopen("2.png", "w");if(NULL == fp_dst){perror("fail to fopen");return -1;}while(1){//第二个参数:每次读一个字节。第三个参数:4096个对象//每次只读一个字节,读4096个对象,循环nret = fread(tmpbuff, 1, sizeof(tmpbuff), fp_src);if(0 == nret){break;}//第三个参数:读nret个对象fwrite(tmpbuff, 1, nret, fp_dst);}fclose(fp_src);fclose(fp_dst);return 0;
}

流的定位

概念:

设置流的偏移量

fseek

ftell

rewind

重新回到开头

从终端输入文件名,得到文件的长度

整体思路

  1. fgets函数,终端接收文件名
  2. fopen打开文件
  3. fseek定位到文件末尾位置
  4. ftell得到此时的len长度
  5. 输出len长度
#include <stdio.h>
#include <string.h>int main(void)
{FILE *fp = NULL;char filename[256] = {0};long len = 0;printf("请输入文件名:\n");fgets(filename, sizeof(filename), stdin);filename[strlen(filename)-1] = '\0';fp = fopen(filename, "r");if(NULL == fp){perror("fail to fopen");return -1;}fseek(fp, 0, SEEK_END);len = ftell(fp);printf("len = %ld\n", len);fclose(fp);return 0;
}

读取BMP图片的宽度和高度

整体思路:

  1. fopen打开bmp图片
  2. fseek偏移18个字节到宽度位置
  3. fread读取宽度和高度
  4. 输出宽度和高度
#include <stdio.h>int main(void)
{FILE *fp = NULL;int width = 0;int height = 0;fp = fopen("test.bmp", "r");if(NULL == fp){perror("fail to fopen");return -1;}fseek(fp, 18, SEEK_SET);fread(&width, 1, sizeof(width), fp);fread(&height, 1, sizeof(height), fp);printf("width = %d, height = %d\n", width, height);return 0;
}

文件IO

概念

        标准IO是由缓存的IO,文件IO没有缓存,适合于通信、硬件设备操作

        标准IO是库函数,文件IO是系统调用

系统调用与库函数

系统调用:是linux内核中的代码,只能在linux系统中使用

库函数:是对系统调用的封装,可以在不同的操作系统中安装并使用,库函数最终还是要调用系统调用完成对应功能

文件IO函数接口

函数接口

文件打开

有三个特殊的文件描述符:

标准输入(0)、标准输出(1)、标准错误(2)

文件描述符特点:

  • 非负整数
  • 取 尚未被占用的最小的非负整数
  • 文件描述符是由上限的,到达上限后再打开会报错
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(void)
{int fd = 0;//r —— O_RDONLY//r+ —— O_RDWR  文件存在读写打开,文件不存在报错fd = open("a,txt", O_RDWR);if(-1 == fd){perror("fail to open");return -1;}close(fd);return 0;
}

关闭文件描述符

标准IO对应的文件IO的打开方式

文件IO读写

write

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>int main(void)
{int fd = 0;char tmpbuff[4096] = {"hello world"};ssize_t nret = 0;fd = open("a.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);if (-1 == fd){perror("fail to open");return -1;}nret = write(fd, tmpbuff, strlen(tmpbuff));printf("实际写入:%ld\n", nret);close(fd);return 0;
}

read

需要打印时,才对siezof(tmpbuff)-1

#include "../head.h"int main(void)
{int fd = 0;char tmpbuff[4096] = {0};ssize_t nret = 0;fd = open("/usr/include/stdio.h", O_RDONLY);if(-1 == fd){perror("fail to open");return -1;}nret = read(fd, tmpbuff, sizeof(tmpbuff)-1);printf("实际接收%ld字节,内容:%s\n", nret, tmpbuff);close(fd);return 0;
}
使用read和write完成对图片的拷贝
#include "../head.h"int main(void)
{int fsrc = 0;int fdst = 0;char tmpbuff[4096] = {0};ssize_t nret = 0;//实际读到的字节数fsrc = open("1.png", O_RDONLY);if(-1 == fsrc){perror("fail to open");return -1;}fdst = open("2.png", O_WRONLY | O_CREAT | O_TRUNC, 0664);if(-1 == fdst){perror("fail to open");return -1;}while (1){nret = read(fsrc, tmpbuff, sizeof(tmpbuff));if(nret <= 0){break;}//第二个参数:缓存区指针;第三个参数:实际读到的字节数write(fdst, tmpbuff, nret);}close(fsrc);close(fdst);return 0;
}

文件描述符偏移量的定位

lseek

#include "../head.h"int main(void)
{FILE ;int fd = 0;char ch = 0;off_t len = 0;fd = open("a.txt", O_WRONLY | O_CREAT, 0664);if (-1 == fd){perror("fail to open");return -1;}len = lseek(fd, 10, SEEK_SET);printf("偏移量:%ld\n", len);ch = 'a';write(fd, &ch, 1);len = lseek(fd, 0, SEEK_CUR);printf("偏移量:%ld\n", len);len = lseek(fd, -5, SEEK_CUR);printf("偏移量:%ld\n", len);ch = 'b';write(fd, &ch, 1);len = lseek(fd, 0, SEEK_SET);printf("偏移量:%ld\n", len);ch = 'c';write(fd, &ch, 1);  close(fd);return 0;
}

文件IO与标准IO互相转换的函数

fileno

根据文件流指针获得文件描述符

fdopen

根据已经打开的文件描述符获得文件流指针

feof

判断文件流指针是否到达末尾

ferror

判断文件流指针是否出错

目录IO

操作方式

  • 打开目录文件
  • 读取目录文件中的没目录想
  • 关闭目录文件

函数接口

opendir

要加上头文件  #include <dirent.h>

closedir

readdir

#include "../head.h"int main(void)
{DIR *dp = NULL;struct dirent *pp = NULL;dp = opendir(".");if(NULL == dp){perror("fail to opendir");return -1;}while (1){pp = readdir(dp);if(NULL == pp){break;}if('.' == pp->d_name[0]){continue;}switch(pp->d_type){case DT_BLK:printf("块设备文件");break;case DT_CHR:printf("字符设备文件");break;case DT_DIR:printf("目录文件");break;case DT_FIFO:printf("管道文件");break;case DT_LNK:printf("链接文件");break;case DT_REG:printf("普通文件");break;case DT_SOCK:printf("套接字文件");break;}printf("\t\t%s\n", pp->d_name);}closedir(dp);return 0;
}
getcwd:获得当前工作目录的绝对路径

chdir:切换当前的工作路径

    mkdir

    • r : 读权限,决定用户是否能够查看目录下所有文件名
    • w :写权限,决定用户是否能够在目录下新建文件
    • x:执行权限,决定用户是否能够进入目录

    rmdir

    递归实现目录的遍历
    //遍历所有目录下的子文件
    #include "../head.h"void listdir(char *dirpath)
    {DIR *dp = NULL;struct dirent *pp = NULL;char tmpbuff[4096] = {0};dp = opendir(dirpath);if(NULL == dp){perror("fail to opendir");printf("failed:%s\n", dirpath);return;}while(1){pp = readdir(dp);if(NULL == pp){break;}if('.' == pp->d_name[0]){continue;}sprintf(tmpbuff, "%s/%s", dirpath, pp->d_name);printf("%s\n", tmpbuff);if(pp->d_type == DT_DIR){listdir(tmpbuff);}}closedir(dp);return;
    }int main(void)
    {listdir("/home/linux");return 0;
    }
    队列实现目录的广度遍历
    #include "../head.h"
    #include "linkqueue.h"void listdir(char *dirpath)
    {linknode *plinkqueue = NULL;char tmppath[256] = {0};char filepath[1024] = {0};DIR *dp = NULL;struct dirent *pp = NULL;plinkqueue = create_empty_linkqueue();enter_linkqueue(plinkqueue, dirpath);while (!is_empty_linkqueue(plinkqueue)){quit_linkqueue(plinkqueue, tmppath);dp = opendir(tmppath);if (NULL == dp){perror("fail to opendir");printf("%s\n", tmppath);return;}while (1){pp = readdir(dp);if (NULL == pp){break;}if ('.' == pp->d_name[0]){continue;}sprintf(filepath, "%s/%s", tmppath, pp->d_name);printf("%s\n", filepath);if (pp->d_type == DT_DIR){enter_linkqueue(plinkqueue, filepath);}}}destroy_linkqueue(&plinkqueue);return;
    }int main(void)
    {listdir("/home/linux");return 0;
    }

    时间相关的函数接口

    时间类型分类

    • time_t类型时间

      •  1970-1-1到现在的秒数
      • 用于时间计算相关逻辑
    • struct tm类型时间

      • 包含年月日时分秒信息
    • char *字符串类型时间

      • 由时间拼接的字符串

    函数接口

    time

                    

    localtime:将秒数转换为结构体时间

    #include "../head.h"int main(void)
    {time_t t;struct tm *ptm = NULL;time_t ret;char *pstr = NULL;//time(&t);t = time(NULL);//获得当前时间的秒数,从1970年开始printf("t = %ld\n", t);ptm = localtime(&t);printf("%04d-%02d-%02d %02d-%02d-%02d\n", ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,ptm->tm_hour, ptm->tm_min, ptm->tm_sec);ret = mktime(ptm);     printf("ret = %ld\n", ret);pstr = ctime(&ret);printf("pstr = %s\n", pstr);return 0;
    }

    mktime:将结构体时间转换为time_t类型

    ctime将Time_t转换为字符型时间

    http://www.dtcms.com/a/330196.html

    相关文章:

  1. imx6ull-驱动开发篇22——Linux 时间管理和内核定时器
  2. 力扣top100(day02-04)--二叉树 01
  3. 18.10 SQuAD数据集实战:5步高效获取与预处理,BERT微调避坑指南
  4. 数据分析可视化学习总结(美妆2)
  5. Python解包技巧全解析
  6. Python 基础语法(一)
  7. 多处理器技术:并行计算的基石与架构演进
  8. 疯狂星期四文案网第38天运营日记
  9. 继《念念有词》后又一作品《双刃》开播 马来西亚新人演员业文Kevin挑战多面角色引期待
  10. CF每日3题(1600)
  11. element-ui 时间线(timeLine)内容分成左右两侧
  12. npm run dev 的作用
  13. Unity_2D动画
  14. 游戏盾的安全作用
  15. RK3568嵌入式音视频硬件编解码4K 60帧 rkmpp FFmpeg7.1 音视频开发
  16. Celery+RabbitMQ+Redis
  17. Traceroute命令使用大全:从原理到实战技巧
  18. IPC Inter-Process Communication(进程间通信)
  19. 2小时构建生产级AI项目:基于ViT的图像分类流水线(含数据清洗→模型解释→云API)(第十七章)
  20. 基于Supervision工具库与YOLOv8模型的高效计算机视觉任务处理与实践
  21. 1.Cursor快速入门与配置
  22. Multisim的使用记录
  23. GQA:从多头检查点训练广义多查询Transformer模型
  24. 蒙以CourseMaker里面的录屏功能真的是完全免费的吗?
  25. C#标签批量打印程序开发
  26. Redis 键扫描优化:从 KEYS 到 SCAN 的优雅升级
  27. Nginx Stream代理绕过网络隔离策略
  28. 论文Review 激光SLAM VoxelMap | RAL 2022 港大MARS出品!| 经典平面特征体素激光SLAM
  29. 第4节 Torchvision
  30. MC0473连营阵图