概述
一、打开及创建
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failedn");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("creat file1 successn");
}
}
return 0;
}
函数返回一个描述符
O_RDONLY:可读
O_WRONLY:可写
O_RDWR:可读可写
ls -l:列出所有文件清单
-rwxr-xr-x 权限
可读:r 4
可写:w 2
执行:x 1
0600 代表 4+2 权限 :可读可写
给文件所有者CLC权限
二、文件的写入
cat file1 查看文本file1的内容
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
char *buf = "wo shi nen die!";
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failedn");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("creat file1 successn");
}
}
printf("open success!n:fd = %dn",fd);
write(fd,buf,strlen(buf));
close(fd);
return 0;
}
文件打开写入后要close
Linux下指针分配8个字节
计算长度不能用sizeof ()要用 strlen()
三、文件的读取
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "wo shi nen die!";
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failedn");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("creat file1 successn");
}
}
printf("open success!n:fd = %dn",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1)
{
printf("write %d byte to fali1n",n_write);
}
close(fd);
open("file1",O_RDWR);
char *readBuf;
readBuf = (char *)malloc(sizeof(n_write+1));
int n_read = read(fd,readBuf,n_write);
printf("read %d byte context:%s",n_read,readBuf);
close(fd);
return 0;
}
因为光标位置 读取时需要关闭再打开file1,使光标移动到最前面在读取。
缓冲区readBuf 读取到readBuf中
四、光标的移动
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "wo shi nen die!";
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failedn");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("creat file1 successn");
}
}
printf("open success!n:fd = %dn",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1)
{
printf("write %d byte to fali1n",n_write);
}
lseek(fd,0,SEEK_SET);
char *readBuf;
readBuf = (char *)malloc(sizeof(n_write+1));
int n_read = read(fd,readBuf,n_write);
printf("read %d byte context:%s",n_read,readBuf);
close(fd);
return 0;
}
~
SEEK_SET:光标移动到初始位置
SEEK_CUR:光标移动到当前位置
SEEK_END:光标移动到高末尾
off_t offset : 偏移大小 正数向右偏移,负数向左偏移
五、利用光标计算文件大小
返回值一个偏移值 from the biginning of the file
六、文件打开创建的补充
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR|O_CREAT|O_EXCL,0600);
if(fd == -1)
{
printf("file1 exsitn");
}
return 0;
}
O_EXCL:若文件存在返回-1(如果同时指定了O_CREAT,而文件已经存在,则出错)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "wo shi nen die!";
fd = open("./file1",O_RDWR|O_APPEND);
printf("open success!n:fd = %dn",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1)
{
printf("write %d byte to fali1n",n_write);
}
close(fd);
return 0;
}
~
O_APPEND:防止文件被覆盖,在其下一行继续写入(每次写时都加到文件的尾端)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "wo shi nen die!";
fd = open("./file1",O_RDWR|O_TRUNC);
printf("open success!n:fd = %dn",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1)
{
printf("write %d byte to fali1n",n_write);
}
close(fd);
return 0;
}
O_TRUNC:将原文件内容全部干掉重新写入
另一个创建函数 creat
宏表示——数字
S_IRUSE ——4-可读
S_IWUSR——2-可写
S_IXUSR——1-可执行
S_IRWXU——7-可读、可写、可执行
七、文件操作原理简述
https://baike.baidu.com/item/%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6/9809582?fr=aladdin
标准输入输出
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int fd;
char readBuf[128];
int n_read = read(0,readBuf,5);
int n_write = write(1,readBuf,strlen(readBuf));
printf("ndonen");
return 0;
}
动态文件、静态文件
习惯上,标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2.
int n_read = read(0,readBuf,5):读取5个字符到readBuf中
文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫静态文件,当我们去open打开一个文件时,Linux内核做的操作包括:内核进程中建立一个打开文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内核中特定地址管理存放(叫动态文件)
打开文件后,对这个文件的读写操作,都是针对内存中的这一份动态文件的,并不是针对静态文件的。当我们对动态文件进行读写以后,此时内存中动态文件和块设备中的静态文件就不同步了,当我们close关闭动态文件时,close内部内核将内存中的动态文件的内容去更新(同步)块设备中的静态文件
为什么这么设计:不直接对块设备直接操作
块设备本身非常不灵活,是按块读写的,而内存是按字节单位操作的,而且可以随机操作,很灵活
八、小应用之实现cp功能
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fdSrc;
int fdDes;
char *readBuf = NULL;
if(argc != 3)
{
printf("param 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);
fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
int n_write = write(fdDes,readBuf,strlen(readBuf));
close(fdSrc);
close(fdDes);
return 0;
}
}
九、配置文件的修改
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char **argv)
{
int fdSrc;
char *readBuf = NULL;
if(argc != 2)
{
printf("wrongn");
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");
if(p==NULL)
{
printf("Not found");
exit(-1);
}
p = p+strlen("LENG=3");
*p = '5';
lseek(fdSrc,0,SEEK_SET);
int n_write = write(fdSrc,readBuf,strlen(readBuf));
close(fdSrc);
return 0;
}
}
strstr
查找 返回值是一个指针指向查找的头
十、写一个整数到文件
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
int data = 100;
int data2 = 0;
fd = open("./file1",O_RDWR);
int n_write = write(fd,&data,sizeof(int));
lseek(fd,0,SEEK_SET);
int n_read = read(fd,&data2,sizeof(int));
printf("data2:%dn",data2);
close(fd);
return 0;
}
该处是一个指针数据类型,所以取地址
十一、写结构体到文件
换汤不换药,取地址,但是链表直接写入可能会出问题,链表是连续的,结构体数组是块
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
int a;
char b;
};
int main()
{
int fd;
struct Test data[2] = {{99,'a'},{100,'b'}};
struct Test data2[2];
fd = open("./file1",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("data2:%dn,%cn",data2[0].a,data2[0].b);
printf("data2:%dn,%cn",data2[1].a,data2[1].b);
close(fd);
return 0;
}
十二、标准C库对文件的引入
C语言第四版第十章
对于这两个名字很类似的函数,对于很多初学者来说,不容易搞清楚它们有什么不同,只知道按照函数用法使用。如果能很好的区分两者,相信大家对于C语言和UNIX系统(包括LINUX)有更深入的了解。
在网上查找了一些资料,但是感觉不够全面,一些答案只是从某个角度阐述,所以让人觉得,这个也对,那个也对。但到底谁的表述更正确呢?其实都是对的,只是解释的视角不同罢了。下面结合个人的理解做一些梳理。
- 来源
从来源的角度看,两者能很好的区分开,这也是两者最显而易见的区别:
open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。
fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。
PS:从来源来看,两者是有千丝万缕的联系的,毕竟C语言的库函数还是需要调用系统API实现的。
-
移植性
这一点从上面的来源就可以推断出来,fopen
是C标准函数,因此拥有良好的移植性;而open
是UNIX系统调用,移植性有限。如windows下相似的功能使用API函数CreateFile
。 -
适用范围
open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(Regular File)。
fopen是用来操纵普通正规文件(Regular File)的。 -
文件IO层次
如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。 -
缓冲
缓冲文件系统
缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
非缓冲文件系统
缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar等。
一句话总结一下,就是open无缓冲,fopen有缓冲。前者与read, write等配合使用, 后者与fread,fwrite等配合使用。
使用fopen函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用还是需要调用系统调用API:read,write);而使用open函数,在文件读写时则每次都需要进行内核态和用户态的切换;表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列的函数快;如果随机访问文件则相反。
这样一总结梳理,相信大家对于两个函数及系列函数有了一个更全面清晰的认识,也应该知道在什么场合下使用什么样的函数更合适,效率更高。
十三、标准C库打开创建读写文件,光标移动
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fd;
char *buf = "wo shi nen die";
char readBuf[128] = {0};
fd = fopen("./zhang.txt","w+");
fwrite(buf,sizeof(char),strlen(buf),fd);
fseek(fd,0,SEEK_SET);
fread(readBuf,sizeof(char),strlen(buf),fd);
printf("%s",readBuf);
fclose(fd);
return 0;
}
fd = fopen("./zhang.txt","w+");
w+ :权限 注意双引号
int write = fwrite((void *ptr, size_t size, size_t nmemb, FILE *stream);
int nread = fwrite((void *ptr, size_t size, size_t nmemb, FILE *stream);
返回值取决于第三个参数 这两个有细微的区别
十四、标准C库写结构体到文件
#include <stdio.h>
#include <string.h>
struct Test
{
int a;
char c;
};
int main()
{
FILE *fd;
struct Test data = {100,'a'};
struct Test data2;
fd = fopen("./file1","w+");
fwrite(&data,sizeof(struct Test),1,fd);
fseek(fd,0,SEEK_SET);
fread(&data2,sizeof(struct Test),1,fd);
printf("%d,%c",data2.a,data2.c);
fclose(fd);
return 0;
}
十五、补充
fputc:
#include <stdio.h>
#include <string.h>
int main()
{
int i;
int len;
FILE *fp;
char *str = "wo shi nen die";
len = strlen(str);
fp = fopen("./test.txt","w+");
for(i=0;i<len,i++)
{
fputc(*str,fp);
str++;
}
fclose(fp);
return 0;
}
feof:判断是否到达文件的尾巴
fgetc
到达文件尾巴返回0
#include <stdio.h>
int main()
{
FILE *fp;
char c;
fp = fopen("./test.txt","r");
while(!feof(fp)) //!取反
{
c = fgetc(fp);
printf("%c",c);
}
fclose(fp);
return 0;
}
最后
以上就是喜悦往事为你收集整理的Linux系统编程 文件的全部内容,希望文章能够帮你解决Linux系统编程 文件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复