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

嵌入式 - Linux软件编程:文件IO

一、概念

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

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

文件 IO 与标准 IO(基于 C 库函数的 IO)是 Linux 中两种主要的 IO 方式,二者的核心差异如下:

特性文件 IO(系统调用)标准 IO(库函数)
缓存机制无用户空间缓存,依赖内核缓存有用户空间缓存(全缓存、行缓存等)
接口类型系统调用(如 open、read、write)库函数(如 fopen、fread、fwrite)
效率频繁调用时效率较低(系统调用开销)效率高(缓存减少系统调用次数)
实时性实时性好(直接与内核交互)实时性差(缓存延迟刷新)
适用场景底层开发、实时性要求高的场景普通文件操作、追求开发效率的场景

二、系统调用与库函数

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

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

三、文件IO函数接口

1. 函数接口:

标准IO                 文件IO

fopen                 open

fclose                 close

fgetc/fputc         read/write

fgets/fputs

fscanf/fprintf

fread/fwrite

fseek/ftell/rewind         lseek

2. 文件打开

原型:
int open(const char *pathname, int flags);  
int open(const char *pathname, int flags, mode_t mode);  

功能:

打开文件,获得操作文件的 文件描述符

参数:
  • pathname:要打开的文件路径
  • flags:打开文件的标志(必须包含 O_RDONLY/O_WRONLY/O_RDWR 三者之一,可选辅助标志如下):
    • O_RDONLY:只读
    • O_WRONLY:只写
    • O_RDWR:读写
    • O_CREAT:文件不存在时创建(需配合 mode 指定文件权限)
    • O_TRUNC:文件存在时,截断为 0(清空内容)
    • O_APPEND:写操作时追加到文件末尾
    • O_EXCL:与 O_CREAT 配合,若文件已存在则报错
返回值:
  • 成功:返回 新文件描述符(非负整数)
  • 失败:返回 -1
注意:
  • 有三个特殊的文件描述符
    • 标准输入: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;// // close(0); //关闭输入流// getchar();// // close(1);// printf("hello");//0664 //八进制//110110100//rw-rw-r--//O_WRONLY:   00000001// O_CREAT:    00000100// O_TRUNC:    00001000// -------------------- |// flags:      00001101  // 所有标志位被合并起来fd = open("a.txt",O_WRONLY | O_CREAT | O_TRUNC,0664);printf("fd = %d\n",fd); //[文件描述符]fd = 3 (从3开始)//0,1,2 被占用(有上限)if(-1 == fd){perror("fail to open");return -1;}//rfd = open("a.txt",O_RDONLY,0664);//r+fd = open("a.txt",O_RDWR,0664);//Wfd = open("a.txt",O_WRONLY | O_CREAT | O_TRUNC,0664);//w+fd = open("a.txt",O_RDWR | O_CREAT | O_TRUNC,0664);//afd = open("a.txt",O_WRONLY | O_APPEND | O_CREAT,0664);//a+fd = open("a.txt",O_RDWR | O_APPEND | O_CREAT,0664);close(fd);return 0;
}

3. 关闭文件描述符

原型:
int close(int fd);  
功能:

关闭文件描述符

4. 标准 I/O 对应的文件 I/O 的打开方式

标准 I/O文件 I/O 打开方式
rO_RDONLY
r+O_RDWR
w`O_WRONLYO_CREATO_TRUNC, 0664`
w+`O_RDWRO_CREATO_TRUNC, 0664`
a`O_WRONLYO_APPENDO_CREAT, 0664`
a+`O_RDWRO_APPENDO_CREAT, 0664`

5. 文件 I/O 读写

1. write
原型:
ssize_t write(int fd, const void *buf, size_t count);  
功能:

向文件描述符 fd 中,写入 buf 指向的 count 个字节 的数据

参数:
  • fd:文件描述符
  • buf:要写入的数据空间 首地址
  • count:要写入的 字节数
返回值:
  • 成功:返回 实际写入的字节数
  • 失败:返回 -1

四、实战练习

//图片拷贝#include<stdio.h>
#include<string.h>int main(void)
{FILE *fp1 = NULL;FILE *fp2 = NULL;size_t nret = 0;char pic[4096] = {0};fp1 = fopen("pp1.png","r");fp2 = fopen("dst.png","w");if(fp1 == NULL || fp2 == NULL){perror("fail to fopen");return -1;}while(1){nret = fread(pic,1,sizeof(pic),fp1);if(nret == 0){break;}fwrite(pic,1,nret,fp2);// fwrite(pic,nret,1,fp2);}fclose(fp1);fclose(fp2);return 0;
}
//2. 统计一个文件中出现最多的字符是哪个?出现了多少次?//    + 使用链表实现//    + 使用数组实现//      0 - 255    cnt[256]//      'a'   -> cnt[97]#include<stdio.h>
#include<string.h>int main(void)
{FILE *fp = NULL;char file[256] = {0};int ch[256] = {0};int i = 0;printf("请输入文件的名字:\n");fgets(file,sizeof(file),stdin);file[strlen(file)-1] = '\0';fp = fopen(file,"r");if(NULL == fp){perror("fail to fopen");return -1;}while(1){i = fgetc(fp);if(EOF == i){break;}ch[i]++;}fclose(fp);int max = 0;for(i = 0;i < 256;i++){if(ch[i] > ch[max]){max = i;}}for(i = 0;i < 256;i++){if(ch[i] == ch[max]){printf("文件中出现最多的字符是'%c'\n",(char)i); printf("其ascii码值为: %d\n",i);printf("出现了%d次\n",ch[i]);}        }return 0;
}

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

相关文章:

  • 零售业CRM实战:如何打通线上线下客户数据?
  • Ansible 基本使用
  • UE官方文档学习 C++ TAarry 查询(三)Contain,Find函数的使用
  • Redis--day4--实战-黑马点评--搭建环境
  • WPS JS宏 通用方法整理汇总 实时更新
  • 【Vue 3 响应式系统深度解析:reactive vs ref 全面对比】
  • MySQL(下)
  • C语言入门完结篇_结构体、枚举、时间函数的、变量类型(C语言划分内存各个区块的方法)、文件操作
  • MyBatis 缓存与 Spring 事务相关笔记
  • Spring-Cache 缓存数据
  • damn the jvm again(2)
  • 编程模型设计空间的决策思路
  • 什么是跨域访问问题,如何解决?
  • Windows怎样配置动态磁盘
  • [SC]SystemC中的SC_FORK和SC_JOIN用法详细介绍
  • android端自定义通话通知
  • VUE的8个生命周期
  • Orange的运维学习日记--41.Ansible基础入门
  • sqli-labs通关笔记-第44关 POST字符型堆叠注入(单引号闭合 手工注入+脚本注入3种方法)
  • demo 英雄热度榜 (条件筛选—高亮切换—列表渲染—日期显示)
  • Full GC 频率优化实战
  • RGWRados::get_obj_state_impl()
  • 25C机场航班调度程序(JS 100)
  • 【智能硬件】2025年儿童智能手表革命:守护隐私的科技堡垒
  • AQS的理解
  • B树索引和B+树索引有什么区别?
  • 编译 BusyBox for ARM 平台
  • 数据结构:图
  • 1、正则表达式入门
  • (LeetCode 每日一题) 2787. 将一个数字表示成幂的和的方案数(动态规划dp+01背包)