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

文件操作:文件IO操作流程及各类函数应用+标准IO与文件IO区别

        文件IO是Linux内核专门为应用层提供的文件操作方法。

一、操作流程

  • 打开文件---open
  • 读写文件---read/write
  • 关闭文件---close

二、open函数

(1)定义:

        int open(const char *pathname, int flags);

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

(2)参数说明

  1. 功能:打开文件并获得一个文件描述符

  2. 参数

  • pathname要打开的文件的文件名
  • flags打开方式

        打开方式的种类

  • O_RDONLY:只读方式打开文件
  • O_WRONLY:只写方式打开文件
  • O_RDWR:可读可写方式打开文件
  • O_CREAT:文件不存在时创建文件
  • O_TRUNC:打开文件时清空文件内容
  • O_APPEND:写文件时从末尾追加内容
  • mode文件操作权限

        遵循 Linux 文件权限规则(如 rwxrwxrwx 对应八进制 0777 ,rw-rw-r-- 对应 0664 ),用于创建新文件时设定初始权限 。

        3.返回值

                成功:返回文件描述符

                失败:-1

<文件权限计算的操作(创建文件时)>

        创建文件指定的 mode 会与系统 umask 按位与(& ),最终确定实际权限 。
示例:mode 设为 0777 ,umask 为 002(即 111 111 101 ),则最终权限:
0777 & 0775 = 0775(八进制计算,对应 rwxrwxr-x ),普通文件通常设 0664 即可满足需求 

(3)文件打开 flags 与标准 I/O 模式对应

标准 I/O 模式文件 I/O(open 函数 flags 组合 )
"r"O_RDONLY
"r+"O_RDWR
"w"`O_WRONLY O_CREATO_TRUNC`(创建并清空文件 )
"w+"`O_WRONLYO_APPENDO_CREAT`(创建并追加写 )
"a"`O_RDWRO_APPENDO_CREAT`(追加写,可读可写 )

(4)文件描述符 file descriptor重要概念

  1. 本质:小的、非负整型数值。
  2. 范围:0 - 1023(共 1024 个,系统限制),是操作系统中已打开文件的标识符 。
  3. 分配原则:从最小未被使用的数值分配,默认打开的三个标准文件(标准输入、输出、错误)对应 fd 为 0、1、2 。
  4. 与标准IO的关联
标准 I/O 类型FILE* 类型
系统默认打开的标准文件及对应 fd- 标准输入(stdin)→ fd = 0
- 标准输出(stdout)→ fd = 1
- 标准错误(stderr)→ fd = 2
新建文件的 fd 分配从 3 开始分配

        打开文件后未及时 close ,会因 fd 有限导致文件描述符泄露,开发需养成操作完文件立即关闭的习惯 。

(5)示例程序

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>int main(int argc , const char *argv[])
{int fd = open("1.txt",O_RDWR  | O_APPEND  | O_CREAT, 0664);if(-1 == fd){printf("open error\n");}printf("fd = %d\n",fd);close(fd);return 0;
}

三、close函数

(1)函数:int close(int fd);

(2)功能:关闭文件

四、read函数

(1)头文件

        #include <unistd.h>

(2)函数

       ssize_t read(int fd, void *buf, size_t count);

3)参数说明

  • 功能:从文件(通过 fd 标识 )中读取数据到缓冲区 buf 。

  • 参数

    • fd:文件描述符(open 获得 )。

    • buf:存储读取数据的内存缓冲区地址 。

    • count:期望读取的字节数 。

  • 返回值

    • 成功:返回实际读取的字节数(可能小于 count ,如读到文件末尾 )。

    • 失败:返回 -1 ;读到文件末尾返回 0 。

(4)示例程序

char buff[1024] = {0}; 
ssize_t cnt = read(fd, buff, sizeof(buff)); 
if (cnt > 0) 
{
printf("buff: %s\n", buff); 
}

五、write函数

(1)头文件

        #include <unistd.h>

(2)函数原型

        ssize_t write(int fd, const void *buf, size_t count);

(3)参数说明

  • 功能:将 buf 中数据写入文件(通过 fd 标识 )。
  • 参数

    • fd:文件描述符 。

    • buf:要写入数据的内存地址 。

    • count:要写入的字节数(通常用 strlen 计算字符串长度,或固定字节数 )。

  • 返回值

    • 成功:返回实际写入的字节数 。

    • 失败:返回 -1 。‘

      (4)程序示例

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>int main(int argc , const char *argv[])
{int fd = open("2.txt",O_WRONLY | O_CREAT | O_TRUNC , 0664);if(-1 == fd){printf("open error\n");return -1;}char str[32] = {"hello"};write(fd,str,strlen(str));char *pstr="hello world";write(fd,pstr,strlen(pstr));write(fd,"how are you",11);close(fd);return 0;
}

读写函数应用示例

1.实现cat功能

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>int main(int argc, const char *argv[])
{if(argc != 2){printf("usage : ./a.out <filename>\n");return -1;}int fd = open(argv[1],O_RDONLY);if(fd < 0){printf("open error\n");return -1;}char buff[1024] = {0};while(1){ssize_t cnt = read(fd,buff, sizeof(buff));if(cnt == 0){return 0;}write(1,buff,cnt);}close(fd);return 0;
}

2.实现拷贝功能

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>int main(int argc, const char *argv[])
{if(argc != 3){printf("usage : ./a.out <srcfile> <dstfile>\n");return -1;}int srcfd = open(argv[1],O_RDONLY);int dstfd = open(argv[2],O_RDWR  | O_APPEND  | O_CREAT,0664);if(-1 == srcfd || -1 == dstfd){printf("open error\n");return -1;}while(1){char buff[1024] = {0};ssize_t cnt = read(srcfd , buff,sizeof(buff));if(cnt == 0){break;}else if(-1 == cnt){printf("read error\n");break;}write(dstfd,buff,cnt);}close(srcfd);close(dstfd);return 0;}   

六、文件定位函数---lseek

(1)头文件

        #include <sys/types.h> + #include <unistd.h>

(2)函数原型

        off_t lseek(int fd, off_t offset, int whence);

(3)参数说明

  • 功能:调整文件读写位置(类似 “光标移动” ),支持随机读写文件 。
  • 参数
    • fd:文件描述符 。
    • offset:偏移量(正数向后移,负数向前移,需结合 whence 理解 )。
    • whence:偏移的参考位置:
      • SEEK_SET:从文件开头算偏移 。
      • SEEK_CUR:从当前读写位置算偏移 。
      • SEEK_END:从文件末尾算偏移 。
  • 返回值
    • 成功:返回当前读写位置相对于文件开头的偏移量 。
    • 失败:返回 -1 。

4.实用场景

  • 求文件大小:lseek(fd, 0, SEEK_END); 返回值即为文件总字节数(需配合变量接收返回值)。
  • 重置读写位置:lseek(fd, 0, SEEK_SET); ,让后续读写回到文件开头 。

七、标准IO和文件IO的区别

对比维度标准 I/O(如 printf、fopen 等 )文件 I/O(如 open、read、write 等 )
归属与移植性属于 C 库函数,移植性强。属于 Linux 系统调用,依赖内核,移植性弱(仅限 Linux 类系统 )。
缓冲区标准IO是系统调用的一次封装,增加了缓冲区,目的是提高数据读写效率。无缓冲区,每次 read/write 直接触发系统调用 。
适用场景主要用于对普通文件的操作。主要应用在对硬件的操作,也可操作普通文件。

八、缓冲区类型(标准 I/O )

标准 I/O 因缓冲区存在,数据并非立即刷新。

(1)行缓冲(1K 缓冲区,约 1024 字节 )

  • 应用场景:终端交互(如 printf 输出到控制台 )。
  • 刷新时机
    • 程序正常结束(隐式触发 )。
    • 遇到换行符(\n )。
    • 调用 fflush(FILE*) 强制刷新 。
    • 缓冲区写满时自动刷新 。

(2)全缓冲(4K 缓冲区,4096 字节 )

  • 应用场景:普通文件读写(如 fopen 打开的文件 )。
  • 刷新时机
    • 程序结束自动刷新 。
    • 调用 fflush(FILE*) 强制刷新 。
    • 文件关闭(fclose )时刷新 。
    • 缓冲区写满时自动刷新 。

(3)无缓冲(0K 缓冲区 )

  • 典型对象:标准错误(stderr ),保证错误信息立即输出(如 fprintf(stderr, ...) )。

补充程序:实现单词的查找

#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;}char *pword = NULL;char *pmean = NULL;char buff[1024] = {0};char word[512] = {0};while (1){fgets(word, sizeof(word), stdin);//hello\nword[strlen(word) -1] = '\0';if (0 == strcmp(word, ".quit")){break;}while (1){char *p = fgets(buff, sizeof(buff), fp);if (NULL == p){printf("Not found\n");break;}pword = strtok(buff, " ");if (pword != NULL){pmean = strtok(NULL, "\r");if (0 == strcmp(word, pword)){printf("%s : %s\n", pword, pmean);break;}}}rewind(fp);}fclose(fp);return 0;}

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

相关文章:

  • Sentinel原理之规则管理
  • 力反馈手套让虚拟培训更加真实
  • GitHub的简单使用方法----(5)
  • AR眼镜新赛道:光波导与MicroOLED如何解决眩晕难题?
  • 低空智航平台技术架构深度解析:如何用AI +空域网格破解黑飞与安全管控难题
  • Ceph数据副本机制详解
  • 【编程实践】关于Vscode无法连接Anaconda解译器的问题
  • PCB题目基础练习1
  • 高速缓冲存储器cache
  • 肖臻《区块链技术与应用》第十讲:深入解析硬分叉与软分叉
  • 力扣top100(day01-03)
  • 基于RAII的智能指针原理和模拟实现智能指针
  • MySQL与其他数据库产品的比较,优势在哪里?
  • 《坐庄》电视剧
  • 基于Python的海量电商用户行为分析与可视化【推荐算法、统计模型、聚类模型、电商指标维度分析】
  • 【4】Transformers快速入门:自然语言模型 vs 统计语言模型
  • [激光原理与应用-257]:理论 - 几何光学 - 光束整形
  • 锁性能基准测试
  • 石英加速度计如何实现高精度测量?
  • 明远智睿T113-i核心板:工业设备制造领域的革新利器
  • 具身智能竞速时刻,百度百舸提供全栈加速方案
  • JVM性能调优技巧
  • Java集合学习之forEach()遍历方法的底层原理
  • 数据科学与计算:爬虫和数据分析案例笔记
  • 01数据结构-Kruskal算法
  • 破译真实感:渲染参数进阶指南——告别塑料感,唤醒材质生命力
  • 01. maven的下载与配置
  • ubuntu24下keychorn键盘连接不了的改建页面的问题修复
  • “生成式UI革命”:Tambo AI如何让你的应用“开口说话、动手搭界面” | 全面深剖、案例实践与未来展望
  • Seed-VC:零样本语音转换与扩散transformer