当前位置:首页>看资讯 >门窗常识>Linux基础——’文件编程‘是怎么回事?

Linux基础——’文件编程‘是怎么回事?

2023-02-10 来源:门窗加盟责任编辑:防火门 浏览数:5 门窗网

核心提示:LINUX基础 ——文件编程篇Linux 一切皆是文件 文件系统(文件夹/文件)硬件设备 ,管道,数据库,Socket等一、文件编程概述:1.应用中比如:账单,游戏进度,配置文件等。 2.用代码操作文件:实现文件创建,打开,编辑等自动化执行。二、计算机如何帮我们自动化完成以上操作呢?操作系统提供了一系列的API 如Linux系统:打开 open读写 write/read光标定位 lseek关闭 close三、文件打开及创建打开/创建文件头文件:#include<sys/tpyes.h> #in

Linux基础——’文件编程‘是怎么回事?

LINUX基础 ——文件编程篇Linux 一切皆是文件 文件系统(文件夹/文件)硬件设备 ,管道,数据库,Socket等一、文件编程概述:1.应用中比如:账单,游戏进度,配置文件等。
2.用代码操作文件:实现文件创建,打开,编辑等自动化执行。
二、计算机如何帮我们自动化完成以上操作呢?操作系统提供了一系列的API 如Linux系统:打开 open读写 write/read光标定位 lseek关闭 close三、文件打开及创建打开/创建文件头文件:#include<sys/tpyes.h> #include<sys/stat.h> #include<fcntl.h>int open(const char *pathname , int flags); //(参数1:字符指针 指向文件路径 , 参数2:整型数权限)int open(const char *pathname , int flags , mode_t mode); //open 返回值是文件描述符——没有文件返回值就无法用write(); 和 read();参数说明:*pathname : //要打开的文件名(含路径,缺省为当前路径)flags :O_RDonLY 只读打开O_WRonLY 只写打开O_RDWR 可读可写可打卡当我们附带了权限后,打开的文件就只能按照这种权限来操作。
以上这三个常数中应当只指定一个。
int creat(const char *filename , mode_t mode) filename:要创建的文件名(包含路径,缺省为当前路径) mode:创建模式 //可读可写可执行 常见创建模式: 宏表示 数字 S_IRUSR 4 可读 S_IWUSR 2 可写 S_IXUSR 1 可执行 S_IRWXU 7 可读,写,执行 示例代码:(在路径/Home/CLC/下创建了file1可读可写可执行文件)#include<sys/types> #include<sys/stat.h> #include<fcntl.h> #include<string> #include<unistd.h> int main() { int fd; char *buf = "test"; fd = creat("/home/CLC/file",S_IRWXU); //S_IRWXU 可读可写可执行 return 0; } ==下列常数是可选择的:==1. O_CREA //若文件不存在则创建它。
使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限。
mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限。
O_CREAT 若文件不存在则创建它 示例代码:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> int main() { int fd; //定义整型返回值 fd = open("./file",O_RDWR); //open指令 打开可读可写file文件返回值 printf("fd = %dn",fd); if(fd == -1){ //若返回值为-1 没有file文件 printf("open file failedn"); fd = open("./file" , O_RDWR | O_CREAT , 0600); //open 指令 若没有file文件 ” | O_CREAT ” 创建file文件 权限0600 6=4+2 所以是rw 可读可写 if(fd>0){ printf("creat file successn"); } } printf("fd=%dn ,fd"); return 0; } 结果:注意:fd = open("./file",O_RDWR); //open指令 打开可读可写file文件返回值fd = open("./file" , O_RDWR | O_CREAT , 0600);// open 指令 若没有file文件 ” | O_CREAT ” 创建file文件 权限0600 6=4+2 所以是rw 可读可写权限0600的含义:—表示普通文件 r (4) 可读 w(2)可写 rw 表示可读可写 x(1)执行 0600 : 6=4+2 所以是rw 可读可写 0是同组 0其他组2. O_EXCL //如果同时指定了OCREAT , 而文件已经存在,则打开失败或者返回-1O_EXCL //如果同时指定了OCREAT , 而文件已经存在,则打开失败或者返回-1 示例代码:#include<sys/types.h> #include<sys/stat.h> #include<fcnt.h> #include<stdio.h> int main(){ int fd; fd = open("./file",O_RDWR | O_CREAT | O_EXCL , 0600); if(fd == -1){ //若返回值为-1 没有file文件 printf("file existn"); return 0; } } 注意:fd = open("./file",O_RDWR | O_CREAT | O_EXCL , 0600);3. O_APPEND//每次写时都加到文件的尾端。
O_APPEND //每次写时都加到文件的尾端 示例代码:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> int main(){ int fd; char *buf = "19990330"; fd = open("./file",O_RDWR | O_APPEND); printf("open susceess: fd = %d n", fd); int n_write = write(fd ,buf,strlen(buf)); if(n_write != -1){ printf("write %d byte to filen",n_write); } close(fd); return 0; } 注意:fd = open("./file",O_RDWR | O_APPEND);4. O_TRUNC属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或者只写 成功打开,则将其长度截断为0。
O_TRUNC属性去打开文件时,如果这个文件中本来是有内容的,把原先内容全部覆盖掉,示例代码:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> int main(){ int fd; char *buf ="19990330"; fd = open("./file",O_RDWR | O_TRUNC); printf("open susceess:fd =%dn",fd); int n_write = write(fd ,buf ,strlen(buf)); if(n_write != -1){ printf("write %d bute to filen",n_write); } close(fd); return 0; } 注意:fd = open("./file",O_RDWR | O_TRUNC);ls-l 是把文件所有内容列出来-rwxr-xr-x 1 CLC book 8478 Fed 9 12:36 mode -rw-r --r -- 1 CLC book 385 Fed 9 12:36 mode.c -rw ------ 1 CLC book 0 Fed 9 12:44 file—表示普通文件 r (4) 可读 w(2)可写 rw 表示可读可写 x(1)执行四、文件写入操作编程写入文件:==write== 头文件: ==#include<unistd.h>==ssize_t write (int fd , const void *buf , size_t count);==//将缓冲区buf指针指向内存数据,写conuct的大小 到 fd里。
==(int fd , const void *buf , size_t count) 参数:(文件描述符 ,【无类型指针是一个缓冲区】,写入文件的大小)文件写入操作示例代码:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> #include<string.h> #include<unistd.h> int main() { int fd; char *buf = "Refuel.CONG"; fd = open("./file",O_RDWR); printf("fd=%dn",fd); if(fd == -1){ printf("open file failedn"); fd = open("./file",O_RDWR | O_CREAT , 0600); if(fd>0){ printf("creat file successn"); } } //ssize_t write(int fd , const void *buf , size_t count); //将缓冲区buf指针指向内存数据,写conut大小到fd。
write(fd,buf,strlen(buf)); printf("fd=%dn",fd); close(fd); //关闭fd文件 return 0; } strlen(); 函数是用来 真正计算有效字符长度用strlen 头文件是:<string.h>五、文件读取操作读取文件:==read== 头文件: ==#include<unistd.h>==ssize_t read(int fd , const void *buf , size_t count); ==//从fd个文件读取count个字节数据放到buf里==返回值:若读取成功,读多少个字节返回多少个字节,若读到尾什么都没读到返回0,读取失败返回-1文件读取示例代码:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> #include<string.h> #include<stdlib.h> int main() { int fd; char *buf ="Refuel.CONG"; fd= open("./file",O_RDWR); printf("fd=%dn",fd); if(fd == -1){ printf("open file failedn"); fd = open("./file", O_RDWR | O_CREAT | ,0600); if(fd>0){ printf("create file successn"); } } int n_write = write(fd,buf,strlen(buf)); if(n_write != -1){ printf("write%d byte to filen",n_write); //若读取成功,返回读到的 ite } char *readBuf; readBuf = (char*)malloc(sizeof(char)*n_write+1); int n_read = read(fd,reafBuf , n_write); printf("read=%d , context:%sn",n_read,readBuf); close(fd); return 0; } 结果什么都没读取到: 是因为光标的原因,光标在写入数据后,光标停在写完的位置,读取的时候光会变后面,什么也没有所以读取不到。
==解决办法:==把光标移动到头。
重新打开文件。
重新打开文件的方式解决光标的问题:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> #include<string.h> #include<stdlib.h> int main() { int fd; char *buf ="Refuel.CONG"; fd= open("./file",O_RDWR); printf("fd=%dn",fd); if(fd == -1){ printf("open file failedn"); fd = open("./file", O_RDWR | O_CREAT | ,0600); if(fd>0){ printf("create file successn"); } } int n_write = write(fd,buf,strlen(buf)); if(n_write != -1){ printf("write%d byte to filen",n_write); //若读取成功,返回读到的 ite } close(fd); //写完数据后关闭文件 fd = open("./file",O_RDWR); //重新打开 char *readBuf; readBuf = (char*)malloc(sizeof(char)*n_write+1); int n_read = read(fd,reafBuf , n_write); printf("read=%d , context:%sn",n_read,readBuf); close(fd); return 0; } 结果为:六、文件光标移动操作光标移动:==lseek== 头文件:==#include<sys/types.h>====#include<unistd.h>==宏:==SEEK_SET== //指向文件的头==SEEK_CUR== //指向当前光标位置==SEEK_END== //指向文件的尾off_t lseek(int fd , off_t offset , int whence); 作用:将文件读写指针相对 whence 移动 offset 个字节 参数说明: (文件描述符,偏移值,固定的位置)#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> #include<string.h> #include<stdlib.h> int main() { int fd; char *buf ="Refuel.CONG"; fd= open("./file",O_RDWR); printf("fd=%dn",fd); if(fd == -1){ printf("open file failedn"); fd = open("./file", O_RDWR | O_CREAT | ,0600); if(fd>0){ printf("create file successn"); } } int n_write = write(fd,buf,strlen(buf)); if(n_write != -1){ printf("write%d byte to filen"n_write); } char *readBuf; readBuf = (char *)malloc(sizeof (char)*n_write+1); lseek (fd,0,SEEK_SET); //参数:(文件描述,偏移值,固定的位置) //lseek(fd,-11 ,SEEK_CUR); //所在光标位置往前偏移11个 int n_read = read(fd ,readBuf,n_write); printf("read=%d,context:%sn",n_write,readBuf); close(fd); return 0; lseek (fd,0,SEEK_SET); //参数:(文件描述,偏移值,固定的位置) lseek(fd,-11,SEEK_CUR); //所在光标位置往前偏移11个七、文件操作原理简述1.文件描述符:对于内核而言,所有打开文件都由文件描述符引用。
文件描述符是一个非负整数。
当打开一个现存文件或者创建一个新文件时,内核向进程返回一个文件描述符。
当读写一个文件时,用open和creat返回的文件描述符标识该文件,将其作为参数传递给read和write。
按照惯例,UNIX shell 使用文件描述符0与进程的标准输入相结合,文件描述符1与标准输出相结合,文件描述符2与标准错误输出相结合。
STDIN_FILENO 、STDOUT_FILENO、STDERR_FILENO这几个宏代替了0,1,2这几个数。
文件描述符,这个数字在一个进程中表示一个特定含义,当我们open一个文件时,操作系统在内存中构建了一些数据结构来表示这个动态文件,然后返回给应用程序一个数字作为文件描述符,这个数字就和我们内存中维护的这个动态文件的这些数据结构绑定上了,以后我们应用程序如果要操作这个动态文件,只需要用这个文件描述符区分。
文件描述符的作用域就是当前进程,除了这个进程文件描述符就没有意义了,open函数打开文件,打开成功返回一个文件描述符,打开失败,返回-1。
2.linux系统默认:标准描述符:标准输入(0) 标准输出(1) 标准错误(3)#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> #include<string.h> #include<stdlib.h> int main(){ int fd; char readBuf[128]; int n_read = read(0,readBuf,5); // 0 标准输入 int n_write = write(1,readBuf,strlen(readBuf)); // 1 标准输出 printf("n end!n"); return 0; } 在这里插入图片描述3.操作文件时候:打开/创建文件 ——> 读取文件/写入文件 ——> 关闭文件==1、在Linux中要操作一个文件,一般是先open打开一个文件,得到文件描述符,然后对文件进行读写操作(或其他操作),最后是close关闭文件即可。
2、强调一点:我们对文件进行操作时,一定要先打开文件,打开成功之后才能操作,如果打开失败,就不用进行后边的操作了,最后读写完成后,一定要关闭文件,否则会造成文件损坏。
3、文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫静态文件,当我们去open打开一个文件时,linux内核做的操作包括:内核在进程中建立一个打开文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内核中特定地址管理存放(叫动态文件)。
read write 都是对动态文件进行操作4、打开文件以后,以后对这个文件的读写操作,都是针对内存中的这一份动态文件的,而并不是针对静态文件的。
当然我们对动态文件进行读写以后,此时内存中动态文件和快设备文件中的静态文件就不同步了,当我们close关闭动态文件名,close内部内核将内存中的动态文件的内容去更新(同步)块设备中的静态文件。
5、为什么这么设计,不直接对块设备直接操作。
块(假设有100字节)设备本身读写非常不灵活,是按块读写的,最小只读100字节,而内存是挤字节单位操作的可而具可以随机操作,很灵活。
静态文件 放入磁盘中的文件是静态文件, 如:桌面上的文件.jpg动态文件 open静态文件后,会在linux内核产生结构体记录文件 如:fd 信息节点,buf(内容,内存)调用close时候,会把所有信息缓存到磁盘中八、文件操作编程小练习—实现cp指令代码:==cp ( src.c //源文件 ,dest.c //复制到的目标文件)==实现cp操作:1.c语言参数: ./a.out _ _ ==2.实现思路:==打开src.c读src到buf创建/打开dest.c将buf写入dest.cclose两个文件==c语言参数:== // 参数(argc是数组)(argv是二级指针是包含数组的数组:是argv里的每一项都是一个数组)#include<stdio.h> int main( int argc , char **agrv) // 参数(argc是数组)(argv是包含数组的数组:是argv里的每一项都是一个数组) { printf("totol params:%dn",argc); printf("No.1 params:%dn",argv[0]); printf("No.2 params:%dn",argv[1]); printf("No.3 params:%dn",argv[2]); return 0; } 输入 :./a.out des src 结果: totol params : 3 No.1 params : ./a.out No.2 params : des No.3 params : src实现mycp操作代码:#include<sys/types.h> #include<sys/stat.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<unistd.h> int main(int argc ,char **argv){ int fdSrc; int fdDest; char *readBuf = NULL; if(argc != 3){ printf("param errorn"); exit(-1); } fdSrc = open(argv[1],O_RDWR); //1. 打开fdSrc.c(源文件) int size = lseek(fdSrc ,0, SEEK_END); //光标记录文件大小 lseek(fdSrc , 0, SEEK_SET); //!!千万记得把 光标回到头 readBuf = (char *)malloc(sizeof(char) *size+8); //开辟readBuf空间大小 int n_read = read(fdSrc,readBuf,size); //2. 读取fdSrc(源文件)到readBuf缓冲区 fdDest = open(argv[2],O_RDWR | O_CREAT | O_TRUNC ,0600); //3. 打开/创建fdDest.c int n_write = write(fdDest,readBuf,strlen(readBuf)); //4. 将readbuf写入到fdDest.c close(fdSrc); //5.关闭两个文件 close(fdDest); return 0; } mycp容易出现的小问题—实现优化:用 lseek来光标计算size数组char *readBuf = NULL; int size = lseek(fdSrc,0,SEEK_END); lseek(fdSrc , 0 ,SEEK_SET); readBuf = (char *)malloc(sizeof(char)*size + 8); 若要是拷贝大于1024的文件就不行 int n_read = read(fdSrc,readBuf,size); //读取大小用lseek查出的大小. 3.目标文件存在并且存在一些数据,拷贝就会覆盖了原来数据的一部分解决方法: O_TRUNC 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或者只写成功打开,则将其长度截断为0fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600); 九、文件编程小应用之修改程序的配置文件==(工作中常用)== 配置文件的修改例如: SPEED=5 LENG=100 SCORE=90 LEVEL=95修改指定内容的思路:找到(要修改的)位置(修改的位置)往后移动到(要改的值 )3. 修改要改的值找寻修改位置时候,用到 strstr() 函数; 功能:用来检索子串在字符串中首次出现的位置修改LENG的值 示例代码:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<stdio.h> #include<string.h> #include<stdlib.h> int main(int argc , char **argv){ int fdSrc; char *readBuf=NULL; if(argc != 2 ){ printf("pararm errorn"); exit(-1); } fdSrc = open(argv[1],O_RDWR); int size = lseek(fdSrc,0,SEEK_END); lseek (fdSrc,0,SEEK_SET); readBuf =(char *)malloc(sizeof(char)*size+8); int n_read= read(fdSrc,readBuf,size); char *p=strstr(readBuf,"LENG="); //找到(要修改的)位置 //参数1 要找的源文件 2.“要找的字符串” if(p==NULL){ printf("not foundn"); exit(-1); } p=p+strlen("LENG="); //移动字符串个字节 *p='0'; //*p 取内容 lseek (fdSrc,0,SEEK_SET); int n_write =write(fdSrc,readBuf,strlen(readBuf)); close(fdSrc); return 0; } 可以把封装成一个函数:void *changefile(int fd,char *readbuf,char* f,char t){ char *p = strstr(readbuf,f); if(p == NULL){ printf("no foundn"); exit(-1); } p = p + strlen(f); *p = t; } int main(int argc,char **argv) { changefile(fdSrc,readBuf,"LENG=",'6'); } 十、写一个整数到文件ssize_t write(int fd , const void *buf , size_t count);//将缓冲区buf指针指向内存数据,写conut大小到fd.ssize_t read(int fd , const void *buf , size_t count);//从fd个文件读取count个字节数据放到buf里1.写入整型数代码:#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<stdio.h> #include<string.h> #include<stdlib.h> int main(){ int fd; int data = 100; int data2 = 0; fd=open("./flie1",O_RDWR); int n_write =write(fd, &data, sizeof(int)); lseek(fd,0,SEEK_SET); int n_read =read(fd, &data2, sizeof(int)); printf("read %dn",data2); close(fd); return 0; } 在这里插入图片描述2.写入结构体代码(1):struct Test { int a; char c; }; int main(){ int fd; int Test data = {100,'a'}; int Test data2 ; fd=open("./flie1",O_RDWR); int n_write =write(fd, &data, sizeof(struct Test)); lseek(fd,0,SEEK_SET); int n_read =read(fd, &data2, sizeof(struct Test)); printf("read %d %sn",data2.a,data2.c); close(fd); return 0; } 3.写入结构体代码(2):struct Test { int a; char c; }; int main(){ int fd; int Test data[2] = {{100,'a'},{101,'b'}}; int Test data2[2]; fd=open("./flie1",O_RDWR); int n_write =write(fd, &data, sizeof(struct Test)*2); lseek(fd,0,SEEK_SET); int n_read =read(fd, &data2, sizeof(struct Test)*2); printf("read %d %sn",data2[0].a,data2[0].c); printf("read %d %sn",data2[1].a,data2[1].c); close(fd); return 0; } 注意写入/读入的 大小: sizeof(struct Test) 乘2缓冲区可以写入 :整数,字符,结构体等十一、标准C库对文件操作引入1. open 和 fopen 的区别1.

打赏
分享到:
0相关评论
阅读上文 >> 她985硕士,拒绝读博,连生4胎:在210㎡的房子里当13年全职太太
阅读下文 >> 最新12月24日全国铝业厂家收购价格汇总信息(附价格表)

大家喜欢看的

  • 品牌
  • 资讯
  • 展会
  • 视频
  • 图片
  • 供应
  • 求购
  • 商城

版权与免责声明:

凡注明稿件来源的内容均为转载稿或由企业用户注册发布,本网转载出于传递更多信息的目的;如转载稿涉及版权问题,请作者联系我们,同时对于用户评论等信息,本网并不意味着赞同其观点或证实其内容的真实性;


本文地址:http://www.menchuang.net/news/36085.html

转载本站原创文章请注明来源:门窗网

推荐新闻

更多

行业专题

更多行业专题

微信“扫一扫”
即可分享此文章

友情链接

门窗网 【测试站】(c)2008-2022 MenChuang.net SYSTEM All Rights Reserved

服务热线: ICP备案号:陕ICP备2022013085号