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

Linux C文件操作

文章目录

    • 文件操作函数
    • 文件系统调用
    • 系统调用与标准函数c的调用的区别
    • 文件的读取位置
      • 标准c函数
      • 系统调用
      • 空洞文件
    • 文件的内存映射操作
    • 文件目录

linux下的文件操作包括两种,一种是使用C函数,一种是使用系统调用。

  • gcc 常用来实现c程序的编译
  • gcc filename.c 编译,链接(自动)后输出可执行文件a.out
  • 只是输入./a.out就可以执行filename程序
  • gcc -o filename filename.o 可以生成一个filename的可执行文件,直接执行filename就可以直接执行代码中的内容(与上一条相比,只是执行输出的名称)
  • gcc -S filename.c 可以生成一个filaname.s的汇编文件,汇编文件与底层执行时一一对应的,可以用来调试
  • gcc -O 可以用来编译优化,但是不是所有情况下都可以做编译优化。
  • 还可以使用gcc -c filename.cgcc -o filename filename.o分步编译、链接

文件操作函数

文件操作函数包括fopen、fgetc、fputc函数等,这是标准的C函数

// 把file.in中给的内容输出给file.out
#include<stdio.h>
#include<stdlib.h>int main(){int c;FILE *in,*out;//定义两个文件指针类型in=fopen("file.in","r");//以只读的方式打开file.in文件,成功后返回文件指针inout=fopen("file.out","w");//以只写的方式打开file.out文件,成功后返回文件outwhile((c=fgetc(in))!=EOF)//从in文件中读,把读出来的数据写到out中fputc(c,out);fclose(in);fclose(out);exit(0);
}
  • FILE * fopen(char *path,char *mode),第一个参数表示路径,第二个参数表示模式,fopen的返回值是一个文件指针,如果文件打开失败则返回一个NULL,可以使用fclose()函数关闭文件:

    • 模式包括<r,w,a>
    • r表示以只读的方式打开,文件指针指向了文件的起始位置,r表示的文件必须存在。
    • w表示以写入的方式打开,如果文件不存在则创建文件,如果文件存在则先清空文件。
    • a表示以追加模式打开,对一个文件的写入,如果文件不存在就创建文件,如果文件存在就在文件末尾追加内容。
    • 如果后面有+表示可读写;
    • 如果后面有b表示打开的是二进制文件
    • 如果后面有t表示打开的是文本文件。
  • char *fgets(char *s,int size,FILE *stream)表示从指定的文件中读下一个字符,返回一个没有符号的字符,或者EOF(end of file),需要读的文件必须是读或者读写的方式打开的,并且文件存在。

  • fputc(char c,FILE * fp)把内容写入到指定文件。

  • 可以使用diff file.in file.out比较两个文件的内容,没有输出表示两个文件一模一样。

  • fclose,最重要的是把文件从内存中写回磁盘。

为了程序的健壮性,可以把以上的文件改为以下,防止读的文件没有权限或者不存在

// 把file.in中给的内容输出给file.out
#include<stdio.h>
#include<stdlib.h>int main(){int c;FILE *in,*out;//定义两个文件指针类型if((in=fopen("file.in","r"))==NULL){//以只读的方式打开file.in文件,成功后返回文件指针inprint("file.in文件不存在!")return 0;}out=fopen("file.out","w");//以只写的方式打开file.out文件,成功后返回文件outwhile((c=fgetc(in))!=EOF)//从in文件中读,把读出来的数据写到out中fputc(c,out);exit(0);
}

文件系统调用

文件描述符以及open、read、write

#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>int main(){char block[1024];int in,out;int nread;if((in=open("file.in",O_RDONLY))==-1){// 3print("文件打开错误!");return 0;}out=open("file.out",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);// 4while((nread=read(in,block,sizeof(block)))>0)write(out,block,nread);return 0;
}
  • int open(constchar*pathname,int flags,mode_t mode);如果成功则返回一个文件描述符(integer,小的非负整数且没有被使用过),否则返回-1;对于open函数来说,第三个参数当且仅当创建新文件(使用O_RDONLY)才是用,用于指定文件的访问权限,比如权限为777;pathname表示要打开或者创建的文件的路径名;flags表示指定文件的打开模式,flags的值包括以下,打开或者创建文件时,至少要使用一个以下命令:

    • O_RDONLY:只读模式
    • O_WRONLY:只写模式
    • O_RDWR:读写模式
    • O_CREAT:文件不存在时创建文件
  • mode的值包括以下

    • S_IRUSR:允许文件的所有者阅读它
    • S_IWUSR:允许文件所有者写它
    • S_IRGRP:允许文件组读取它
    • S_IWGRP: 允许文件组编写它

linux下任何一个进程都有3个默认打开的文件描述符:0表示标准输入(键盘),1表示标准输出(显示器),2表示标准错误输出(显示器)

  • ssize_t read(int fd, void *buf, size_t count);表示读取指定字节数的数据到缓冲区buff中,同时文件的当前位置向后移动;读取成功返回读取的字节数,出错返回-1并且设置errno,如果在调用read之前已经到达文件末尾则返回0(例如,距文件末尾还有30个字节而请求读100个字节,则read返回30,下次read将返回0);

  • ssize_t write(int fd, const void *buf, size_t count); 成功返回写入的字节数,出错返回-1并设置errno写常规文件时

系统调用与标准函数c的调用的区别

使用time 文件路径,可以知道文件运行所需要的时间
使用scrace 文件路径,可以跟踪文件

  • 使用fgetc或者fputc的时候,它底层的调用还是调用了read和write,但是在读取的时候做了一个系统的优化,也就是一次性读取了多个字节的内容,表面上看起来只读取一个字符,实际上底层中读取的是多个字节的字符。

  • 注意系统调用这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。比如用fgetc读一个字节,fgetc有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE结构体中记录的读写位置是1

文件的读取位置

标准c函数

标准的c函数中,不可以对FILE的文件指针直接进行++,–,可以使用fseek函数来控制文件的读写指针。

  • int fseek(FILE *stream, long offset, int fromwhere);重定位流上的文件指针,函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere为基准,偏移offset个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置;返回值: 成功,返回0,否则返回其他值;第一个参数stream为文件指针;第二个参数offset为偏移量,整数表示正向偏移,负数表示负向偏移;第三个参数origin设定从文件的哪里开始偏移,可能取值为:

    • SEEK_SET: 文件开头,用0表示
    • SEEK_CUR: 当前位置,用1表示
    • SEEK_END: 文件结尾,用2表示
  • fseek(fp,100L,0);把fp指针移动到离文件开头100字节处;
    fseek(fp,100L,1);把fp指针移动到离文件当前位置100字节处;
    ffseek(fp,-100L,2);把fp指针退回到离文件结尾100字节处。

系统调用

系统调用使用lseek来调用文件的文件位置,与c函数调用相比,c文件调用使用的是文件指针,而系统调用使用的是文件描述符号

  • off_t lseek(int fd, off_t offset, int whence);fd表示函数描述符,参数含义与上面的c函数调用一致。

空洞文件

可以使用以上的fseek和lseek去创建一个空洞文件
① 空洞文件就是这个文件有一段是空的;
② 普通文件中间不能有空,write文件时从前往后移动文件指针,依次写入;
③ 用lseek往后跳过一段,就形成空洞文件;
④ 空洞文件对多线程共同操作文件非常有用。需要创建一个很大文件时,从头开始依次创建时间很长,可以将文件分成多段,多个线程操作每个线程负责其中一段的写入。

文件的内存映射操作

  • mmap是一种内存映射文件的方法,即将一个文件或者其他的映射对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟控件中一段虚拟地址的映射关系。实现这种映射关系之后,进程可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,也就是对文件的操作不必调用read或者write等系统调用函数,相同的,在内核空间内这一段的区域也直接改为用户空间,从而实现不同进程的文件的共享。
  • 使用mmap进行映射,会得到一个磁盘和某一个文件的地址相同的地址,当往这个地址写内容的时候,内容会直接写到文件中,比正常的系统调用要少一次拷贝的过程。
  • 正常调用写文件的流程图
    在这里插入图片描述

  • mmp内存映射写文件的流程图
    在这里插入图片描述

  • void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)第一个参数表示映射的地址,如果地址设置为NULL,内核会自动挑一个地址来进行映射;第二个参数表示映射有多长;第三个参数描述了要求的内存保护,包括PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE;最后一个参数表明如果对内存进行修改能否被其他的进程看到,包括MAP_SHARED和MAP_PRIVATE。

#include<stdio.h>
#include<unistd.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<stdlib.h>typedef strucy{int integer;char string[24];
}RECORD;#define NRECORDS(100)int main(){RECORD record,*mapped;int i,f;FILE *fp;fp=fopen("records.dat","w+");for(i=0;i<NRECORDS;i++){record.integer=i;sprintf(record.string,"RECORD-%d",i);fwrite(&record,sizeof(record),1,fp);//写record的数据,长度为record的大小,写一次,写到fp文件中}fclose(fp);fp=fopen("records.dat","r+");fseek(fp,43*sizeof(record),SEEK_SET);fread(&record,sizeof(record),1,fp);//修改fp的数据record.integer=143;sprintf(record.string,"RECORD-%d",record.integer);//修改后写回fseek(fp,-1*sizeof(record),SEEK_CUR);fwrite(&record,sizeof(record),1,fp);fclose(fp);//----------------------------------------------------------//使用mmapf=open("records.dat",O_RDWR);mapped=(RECORD *)mmap(0,NRECORDS*sizeof(record),PROT_RDAD|PROT_WRITE,MAP_SHARED,f,0);//第一个参数0表示内核挑选映射的地址;第二个参数表示映射的大小;第三个参数表示权限,可读可写;第四个参数表示可以共享;第五个参数表示被映射的文件;第六个参数表示映射从文件起始的位置开始的偏移量。执行完成后,整个文件全部映射到内存中,相当于一个数组mappedmapped[43],integer=243;sprintf(mapped[43].string,"RECORD-%d",mapped[43].integer);//操作数组一样操作内存msync((void*)mapped,NRECORDS*sizeof(record),MS_ASYNC);//把内存和辅存中的文件同步起来munmap((void*)mapped,NRECORDS*sizeof(record));//解开映射close(f);return 0;
}

文件目录

文件目录对应的是文件的属性信息,FCB文件控制块,存放文件的属性信息;文件的属性信息与文件的实体不是存在在一个位置上的,把文件的属性信息存放在一个位置,这一类的文件叫做目录文件,也就是windows上的文件夹

#include<unistd.h>
#include<stdio.h>
#include<dirent.h>
#include<string.h>
#include<sys/stat.h>
#include<stdlib.h>void printdir(char *dir,int depth){DIR *dp;struct dirent *entry;struct stat statbuf;if((dp=opendir(dir))==NULL){fprintf(stderr,"cannot open directory:%s\n",dir);return;}chdir(dir);while((entry=readdir(dp))!=NULL){lstat(entry->d_name,&statbuf);if(S_ISDIR(statbuf.st_mode)){if(strcmp(".",entry->d_name)==0||strcmp("..",entry->d_name)==0)continue;printf("%*s%s/\n",depth,"",entry->d_name);printdir(entry->d_name,depth+4);//递归调用,深度优先搜索}else printf("%*s%s\n",depth,"",entry->d_name);}chdir("..");closedir(dp);
}int main(){printf("Directory scan of /home:\n");printdir("/home",0);printf("done\n");return 0;
}

相关文章:

Linux C文件操作

文章目录 文件操作函数文件系统调用系统调用与标准函数c的调用的区别文件的读取位置标准c函数系统调用空洞文件 文件的内存映射操作文件目录 linux下的文件操作包括两种&#xff0c;一种是使用C函数&#xff0c;一种是使用系统调用。 gcc 常用来实现c程序的编译gcc filename.c …...

基于Cucumber的行为驱动开发(BDD)实例

本篇介绍 Cucumber 的基本使用&#xff0c; 因为Cucumber是BDD的工具&#xff0c; 所以首先需要弄清楚什么是BDD&#xff0c;而在介绍BDD之前&#xff0c;先看看常见的软件开发方法。 常见的软件开发方法 面向过程开发&#xff08;Procedural Development&#xff09;&#x…...

十六、代码校验(2)

本章概要 前置条件 断言&#xff08;Assertions&#xff09;Java 断言语法Guava 断言使用断言进行契约式设计检查指令前置条件后置条件不变性放松 DbC 检查或非常严格的 DbCDbC 单元测试 前置条件 前置条件的概念来自于契约式设计(Design By Contract, DbC), 利用断言机制…...

安卓 kotlin-supportFragmentManager报红

如果你继承baseActivity 请查看 是不是继承 AppCompatActivity...

linux中安装RocketMQ以及dashboard

前提&#xff1a; 需要安装jdk8 上传下面的文件到服务器中 新建目录 mkdir rocketmq 将下载后的压缩包上传到阿里云服务器或者虚拟机中去&#xff0c;并解压 unzip rocketmq-all-4.9.2-bin-release.zip 配置环境变量 vim /etc/profile 配置内容&#xff1a; export NAM…...

Android kotlin内联函数(inline)的详解与原理

一、介绍 在kotlin中&#xff0c;有一种函数叫内联函数&#xff0c;这种函数标识符是inline&#xff0c;但是好多人对这个函数的理解只停留在八股文中&#xff0c;内容函数的用法和普通函数没有区别&#xff0c;但是在编译原理上是有&#xff0c;对程序的性能有一定的影响。 二…...

林沛满---一个面试建议

在应聘一个技术职位之前&#xff0c;做好充分的准备无疑能大大提高成功率。这里所说的准备并不是指押题&#xff0c;因为有经验的面试官往往准备了海量的题库&#xff0c;押中的概率太低。比如我有位同事的题库里有上百道题&#xff0c;内容涵盖了编程、操作系统、网络、存储……...

CMake教程-第 5 步:安装和测试

CMake教程-第 5 步&#xff1a;安装和测试 1 CMake教程介绍2 学习步骤Step 1: A Basic Starting PointStep 2: Adding a LibraryStep 3: Adding Usage Requirements for a LibraryStep 4: Adding Generator ExpressionsStep 5: Installing and TestingStep 6: Adding Support f…...

移动应用-Android开发基础\核心知识点

Android开发基础 知识点 1 介绍了解2 系统体系架构3 四大应用组件4 移动操作系统优缺点5 开发工具6 配置工具7 下载相关资源8JDK下载安装流程9配置好SDK和JDK环境10 第一个Hello word11 AS开发前常用设置12模拟器使用运行13 真机调试14 AndroidUI基础布局15 加载展示XML布局16…...

Java读取并转换字符串中的浮点数

在写Android接收蓝牙数据的时候&#xff0c;由于传过来的蓝牙数据转换后都为字符串格式&#xff0c;但是需要从其中提取出来浮点数&#xff0c;所以通过查阅资料写出了从字符串中提取并转换为浮点数的方法&#xff0c;特记录下来以供参考。 目录 原始数据内容 提取字符串中的…...

SQL: 索引原理与创建索引的规范

SQL 索引是一种数据结构&#xff0c;用于加速数据库查询操作。它通过在表的列上创建索引&#xff0c;提供了一种快速查找数据的方法&#xff0c;减少了数据库的扫描和比较操作&#xff0c;从而提高了查询性能。索引根据其实现方式可以分为多种类型&#xff0c;如 B-树索引、哈希…...

基于STM32_DS18B20单总线传感器驱动

基于STM32_DS18B20单总线传感器驱动 文章目录 基于STM32_DS18B20单总线传感器驱动前言一、BS18B20&#xff1f;二、原理1.复位与检验2.基本命令3.唯一ROM识别码4.温度转换 三、驱动代码四、注意事项 前言 本文以一款典型的单总线传感器及其驱动——DS18B20为例&#xff0c;简单…...

目标识别项目实战:基于Yolov7-LPRNet的动态车牌目标识别算法模型(三)

前言 目标识别如今以及迭代了这么多年&#xff0c;普遍受大家认可和欢迎的目标识别框架就是YOLO了。按照官方描述&#xff0c;YOLOv8 是一个 SOTA 模型&#xff0c;它建立在以前 YOLO 版本的成功基础上&#xff0c;并引入了新的功能和改进&#xff0c;以进一步提升性能和灵活性…...

springboot线程池创建与使用

/*** author: zcs* Title: TaskPoolConfig* Description: 线程池配置* date: 2023/10/11 17:52*/ Component public class TaskPoolConfig {Bean(name "threadPoolTaskExecutor")public Executor taskExecutor() {ThreadPoolTaskExecutor taskExecutor new ThreadP…...

UDP和TCP特点(部分)对比:

传输层的两个主要协议&#xff1a;TCP 和 UDP UDP和TCP特点&#xff08;部分&#xff09;对比&#xff1a; UDP&#xff1a;无连接&#xff0c; 不可靠传输&#xff0c; 面向数据报&#xff0c; 全双工。 TCP&#xff1a;有连接&#xff0c; 可靠传输&#xff0c; 面向字节流…...

PostMan环境变量、全局变量、动态参数使用

一、环境准备 postmanmoco [{"description": "登录认证","request": {"uri": "/login","method": "post","forms": {"user": "admin","password": "a123…...

服务器数据恢复-服务器硬盘指示灯黄灯闪烁的数据恢复案例

服务器数据恢复环境&#xff1a; 服务器面板上的硬盘指示灯显示黄色是一种警告&#xff0c;提示指示灯对应的服务器硬盘已经被服务器识别出存在故障&#xff0c;硬盘即将下线。如果出现这种情况&#xff0c;建议服务器管理员/运维人员及时用完好的硬盘替换显示黄色指示灯对应的…...

ts 分发

在 TypeScript 中&#xff0c;"分发"&#xff08;distributive&#xff09;是指在条件类型中的联合类型上自动进行类型推断的机制。当使用条件类型操作联合类型时&#xff0c;TypeScript 会自动将联合类型中的每个成员都应用该条件类型。 下面是一个示例&#xff1a…...

SQL中的group by使用注意事项

在 SQL 中&#xff0c;GROUP BY 语句用于将查询结果按照指定的列进行分组&#xff0c;并对每个分组计算聚合函数&#xff08;如 SUM、AVG、COUNT 等&#xff09;的值。一般情况下&#xff0c;如果查询中包含聚合函数&#xff0c;那么就需要使用 GROUP BY 语句将查询结果按照指定…...

矩阵剪辑系统源码----pc/手机端双开发

剪辑系统&#xff0c;剪辑矩阵系统&#xff0c;剪辑矩阵系统主要是针对抖音、快手、bili平台的一个工具&#xff0c;今天就来给大家交流一下这 个产品的主要功能以及构成。剪辑矩阵系统&#xff0c;矩阵剪辑系统源码-这产品主要功能就是一个视频剪辑功能&#xff0c;这个视频剪…...

0基础学习VR全景平台篇 第106篇:认识调色软件Lightroom

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 正式开讲之前需要先引出一个概念&#xff1a;到底什么是调色? 比如说上面这张照片&#xff0c;你可能会具体的指出照片中的元素有天空、山脉、草地等…… 如果我们跳出我们的固…...

React如何优化减少组件间的重新Render

目前写了不少React的项目&#xff0c;发现React有些特点更灵活和注重细节&#xff0c;很多东西需要有一定的内功才能掌握好&#xff1b;比如在项目中常常遇到的组件重复渲染&#xff0c;有时候组件重复渲染如果内容是纯文本&#xff0c;不打印日志就不容易发现重复渲染了&#…...

mysql面试题44:MySQL数据库cpu飙升的话,要怎么处理?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:MySQL数据库cpu飙升的话,要怎么处理呢? 当MySQL数据库的CPU使用率飙升时,可能表示数据库负载过重或存在性能问题。以下是处理MySQL数据库CPU飙…...

动画圆圈文字标志效果

效果展示 CSS 知识点 实现圆圈文字animation 属性回顾 实现思路 从效果的实现思路很简单&#xff0c;其实就是两个圆圈就可以实现。外层大圆&#xff08;灰色&#xff09;用于圆圈文字的展示&#xff0c;而内圆&#xff08;藏青色&#xff09;主要用于存放 Logo 图片。布局采…...

【数据结构】二叉树--顺序结构及实现 (堆)

目录 一 二叉树的顺序结构 二 堆的概念及结构 三 堆的实现 1 包含所有接口 (Heap.h) 2 初始化,销毁和交换&#xff08;Heap.c) 3 向上调整&#xff08;Heap.c) 4 插入&#xff08;Heap.c) ​5 向下调整&#xff08;Heap.c) 6 删除&#xff08;Heap.c) ​7 打印&#…...

适用于嵌入式单片机的差分升级通用库

转至&#xff1a;痞子衡嵌入式半月刊&#xff1a;第 81 期 1、mcu_bsdiff_upgrade - 适用于嵌入式单片机的差分升级通用库 mcu_bsdiff_upgrade 是一款适用于嵌入式单片机的差分升级库&#xff0c;通用所有单片机&#xff0c;如stm32、华大、复旦微、瑞萨等。适合嵌入式的差分升…...

Exposure Normalization and Compensation for Multiple-Exposure Correction 论文阅读笔记

这是CVPR2022的一篇曝光校正的文章&#xff0c;是中科大的。一作作者按同样的思路&#xff08;现有方法加一个自己设计的即插即用模块以提高性能的思路&#xff09;在CVPR2023也发了一篇文章&#xff0c;名字是Learning Sample Relationship for Exposure Correction。 文章的…...

Arduino驱动BMI160 6轴惯性运动传感器(惯性测量传感器篇)

目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序...

数据挖掘实战(3):如何对比特币走势进行预测?

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…...

巴以冲突中暴露的摄像头正对安全构成威胁

巴以冲突爆发后&#xff0c;许多配置不当的安全摄像头正暴露给黑客活动分子&#xff0c;使其周遭人员面临巨大安全风险。 Cyber​​news 研究人员发现&#xff0c;在以色列至少有165 个暴露的联网 RTSP 摄像头&#xff0c;在巴勒斯坦有 29 个暴露的 RTSP 摄像头。在巴勒斯坦&am…...