在windows中手动修改文件操作步骤:打开\创建文档,编辑文档,保存文档,关闭文档。在Linux中就是用代码操作文件使计算机自动化完成以上步骤。
Linux为此提供了一系列API,打开\创建文件:open,读写:write\read,光标定位:lseek,关闭:close
文件的打开
![](https://img-blog.csdnimg.cn/img_convert/a35e58cea8e1d8422df7d9adb002a30d.png)
需要包含的头文件:使用man查询open,可以看到要使用open必须包含3个头文件,分别是:<sys/types.h>,<sys/stat.h>,<fcntl.h>
返回值:open函数有整数返回值,返回文件的文件描述符,用来区分不同的文件,相当于文件的索引。当文件打开成功时,返回的是非负整数,打开失败时返回负数
参数含义:
pathname:要打开的文件名(含路径,缺省位当前路径)
flags:打开方式,有三种方式,分别是O_RDONLY只读打开, O_WRONLY只写打开, O_RDWR 可读可写打开。
当附带了权限后,打开的文件就只能按照这种权限来操作,比如,我使用O_RDONLY打开文件之后,我不能对文件进行写操作,我只能读
以上3个参数中应当只指定一个,下列的参数是可以选择的:
O-CREAT 若文件不存在则创建它。使用此选项是,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限
O_EXCL 如果同时制定了OCREAT,而文件已经存在,则返回-1
O_APPEND 每次写时都加到文件的尾端
O_TRUNC 若文件种本来有内容,而且位只读或只写成功打开,则将其长度截短为0
mode:一定是再flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限。
作用:打开一个文件,并返回该文件的文件描述符,以便于对其进行读写等操作
相关应用
//打开当面目录下的file1文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd=open("./file1",O_RDWR);
printf("fd=%d\n",fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/dfb10a907b607b1cdaaf82b14374c6c7.png)
创建file1,使用可读可写的方式打开file1文件,编译运行,可以看到返回值为3
![](https://img-blog.csdnimg.cn/img_convert/d3a81dc65aa655b6a12314e8ab894fff.png)
删除file1,再运行代码对其进行打开操作,返回值为-1
//打开当前目录下的file1文件
//当打开文件失败时,创建该文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 failed\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);//0600是文件的访问权限为文件所有者可读可写
if(fd>0){
printf("create file1 successed\n");
}
}
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/ccbcd4691b2731bbfa3907116887fa40.png)
文件的创建
![](https://img-blog.csdnimg.cn/img_convert/d8cca773c287b92ed6ddf49e1134f707.png)
需要包含的头文件:<sys/types.h>, <sys/stat.h>, <fcntl.h>
返回值:fd文件描述符
参数含义:
pathname:要创建的文件名(含路径,缺省位当前路径)
mode:创建模式
S_IRUSR: 可读
S_IWUSR: 可写
S_IXUSR: 可执行
S_IRWXU: 可读可写可执行
作用:从buf缓冲区中写入count个字节到文件中
相关应用:
//在当前目录下创建一个可读可写可执行得到file2文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
int main()
{
int fd;
char *buf="write file";
fd =creat("./file2",S_IRWXU);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/71f8775bd66a66f697d5bfd4be34cbd3.png)
文件写入操作
![](https://img-blog.csdnimg.cn/img_convert/6c32aa1162765045b0f074d4cce0ef32.png)
需要包含的头文件:<unistd.h>
返回值:写入成功,返回写入的字节个数,写入失败返回-1
参数含义:fd:文件描述符,buf:缓冲区 ,count:写入字节数
作用:从buf缓冲区中写入count个字节到文件中
相关应用:
//将“write file”写入file1文件中
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
int main()
{
int fd;
char *buf="write file";
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 failed\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 successed\n");
}
}
printf("open success fd=%d\n",fd);
write(fd,buf,strlen(buf));//此处不能使用sizeof,必须使用strlen,sizeof计算的是buf指针的大小,strlen计算的才是指针指向内容的字节大小
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/1dbeba9ac9bf17eae13ed3d646891498.png)
文件读取操作
![](https://img-blog.csdnimg.cn/img_convert/e2e8c2e44fe855d3e7dae0749a5d8c61.png)
需要包含的头文件:<unistd.h>
返回值:读取成功,读到多少字节就返回多少;读取失败返回0;读取错误返回-1
参数含义:fd:文件描述符,buf:缓冲区 ,count:读取字节数
作用:从文件中读取count个字节到buf缓冲区
相关应用:
//读取file1文件中的内容
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf="write file";
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 failed\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 successed\n");
}
}
printf("open success fd=%d\n",fd);
int cnt_write=write(fd,buf,strlen(buf));
if(cnt_write !=-1){
printf("write %d byte to file1\n",cnt_write);
}
close(fd);
fd=open("./file1",O_RDWR);//此处关闭文件再重新打开的目的是让光标重新回到文件头,这样才能读取到写入的内容,也可以使用光标重定位lseek来进行此操作
char *readBuf;
readBuf=(char *)malloc(sizeof(char)*cnt_write+1);//这里必须对readBUf进行空间开辟,不然readBuf没有具体的指向,会发生段错误。
int cnt_read=read(fd,readBuf,cnt_write);//读取的大小不一定必须是写入的大小,可以是任意值,但是读取到的内容,只有写入的内容那么大,比如读取的是100字节,但是读取完之后的内容依然只有10字节
printf("read %d ,context:%s\n",cnt_read,readBuf);
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/4993c7990d76779e9a85de1a38b5a519.png)
文件光标移动操作
在进行读取时,我们使用了关闭文件再重新打开文件的方式,这种方式就有点垃圾了,我们可以使用lessk直接移动光标
![](https://img-blog.csdnimg.cn/img_convert/c90c5590f26e01435e6d35ff841d892f.png)
需要包含的头文件:<sys/types.h>,<unistd.h>
返回值:调用成功,返回对于文件头的偏移值
参数含义:
fd:文件描述符
offset:当offset为负数,对于whence往前移,当offset为正数,对于whence往后移
whence:
SEEK_SET:文件头
SEEK_CUR:当前位置
SEEK_END:文件尾
作用:将文件读写指针相对whence移动offset个字节
相关应用:
//对于前面的读取文件内容的代码,进行修改
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf="write file";
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 failed\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 successed\n");
}
}
printf("open success fd=%d\n",fd);
int cnt_write=write(fd,buf,strlen(buf));
if(cnt_write !=-1){
printf("write %d byte to file1\n",cnt_write);
}
// close(fd);
// fd=open("./file1",O_RDWR);
lseek(fd,-cnt_write,SEEK_END);//从文件尾像前移动写入的字节数,也相当于lssek(fd,0,SEEK_SET)
char *readBuf;
readBuf=(char *)malloc(sizeof(char)*cnt_write+1);
int cnt_read=read(fd,readBuf,cnt_write);
printf("read %d ,context:%s\n",cnt_read,readBuf);
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/3f87457196b6e62ac22524cea5d3d847.png)
//巧用lseek对文件大小进行计算
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf="write file";
fd=open("./file1",O_RDWR);
int fileSize=lseek(fd,0,SEEK_END);//利用lseek的返回值是对于文件头的偏移值,我们可以直接将光标移到文件尾,就可以巧妙的计算文件的字节大小了
printf("file size is:%d\n",fileSize);
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/b6dcc7873ae5fdd31303f6b862b0424e.png)
文件编程应用1——实现Linux cp命令
//main函数的参数,来读取cp aa bb命令中的两个文件
#include <stdio.h>
int main(int argc, char **argv) //argc是参数的总个数,argv是数组指针,每个数组指针指向的内容是相应的参数
{
printf("total paeams:%d",argc);
printf("No.1 params:%s\n",argv[0]);
printf("No.2 params:%s\n",argv[1]);
printf("No.3 params:%s\n",argv[2]);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/4631542ca9e61e87a776350502096561.png)
//编写代码实现Linux cp命令
/*实现思路:打开源文件src.c,读源文件src.c到缓冲区buf,打开/创建目标文件des.c,将缓冲区buf的内容写入到目标des.c,关闭两个文件*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int fd_src;
int fd_des;
char *readBuf=NULL;
if(argc !=3){
printf("param error\n");
exit(-1);
}
fd_src=open(argv[1],O_RDWR);
int size=lseek(fd_src,0,SEEK_END);
lseek(fd_src,0,SEEK_SET);
readBuf=(char *)malloc(sizeof(char)*size+8);
int n_read=read(fd_src,readBuf,size);
fd_des=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
int n_write=write(fd_des,readBuf,strlen(readBuf));
close(fd_src);
close(fd_des);
return 0;
}
文件编程应用2——修改程序的配置文件
在这之前需要先了解strstr()这个API
![](https://img-blog.csdnimg.cn/img_convert/ef47650139471c5562dbe859bbdef23d.png)
需要包含的头文件:<string.h>
返回值:需要找的特定字符串出现的首位置,返回的是一个字符型指针
参数含义:haystack:要操作的字符串 ,needle:找到的字符串
作用:从字符串中找出特定的字符串
现有配置文件如下,将LENG=3 修改为 LENG=5
![](https://img-blog.csdnimg.cn/img_convert/e78fe3bf53c993be815f91b073213dea.png)
//修改LENG=3为LENG=5的步骤如下
//1.找到LENG=3出现的首位置
//2.该位置记录下来
//3.再将位置向后移动到需要修改的地方,即移动到3的位置,再将5赋值给指针指向的位置
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int fd_src;
char *readBuf=NULL;
if(argc !=2){
printf("param error\n");
exit(-1);
}
fd_src=open(argv[1],O_RDWR);
int size=lseek(fd_src,0,SEEK_END);
lseek(fd_src,0,SEEK_SET);
readBuf=(char *)malloc(sizeof(char)*size+8);
int n_read=read(fd_src,readBuf,size);
char *p=strstr(readBuf,"LENG=");
if(p==NULL){
printf("not found");
exit(-1);
}
p=p+strlen("LENG+");
*p='5';//一定要是字符'5',在文件中的内容都是字符型的
lseek(fd_src,0,SEEK_SET);//光标重新定位,让缓冲区中修改后的内容重新覆盖掉源文件中的内容
int n_write=write(fd_src,readBuf,strlen(readBuf));
close(fd_src);
return 0;
}
编译运行之后,再打开需要修改的文件,就可以看到已经修改好了
![](https://img-blog.csdnimg.cn/img_convert/4f7c2484fdaadbdead1c909b12dee82a.png)
写一个整数到文件
上面修改文件配置文件时,写入文件的是一个字符,并且文件中的内容都是字符型的,那么怎样才能将一个整型数写入到文件呢
![](https://img-blog.csdnimg.cn/img_convert/96e890832efe3b9f90fe6749eaa1857f.png)
可以从手册中看到,buf其实是一个无类型的指针,所以不仅仅是可以传递一个字符型指针,也可以是一个指向整型数的地址
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int fd;
int x=100;
int y=0;
fd=open("./file2",O_RDWR);
int n_write=write(fd,&x,sizeof(int));//将x地址指向的值写入到file2里面
lseek(fd,0,SEEK_SET);//光标重定位,将光标定位到文件头
int n_read=read(fd,&y,sizeof(int));//从file2中将x读到y所指向的地址空间中
printf("read:%d",y);
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/d5ebfed0acbb9098904ecd7fc18978d6.png)
写结构体数组到文件
写结构体到文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct test
{
int a;
char b;
};
int main()
{
int fd;
struct test x={100,'a'};
struct test y;
fd=open("./file2",O_RDWR);
int n_write=write(fd,&x,sizeof(struct test));
lseek(fd,0,SEEK_SET);
int n_read=read(fd,&y,sizeof(struct test));
printf("read:%d,%c\n",y.a,y.b);
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/fb88e82545bd1afd3c4e264c697a3d72.png)
写结构体数组到文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct test
{
int a;
char b;
};
int main()
{
int fd;
struct test x[2]={{100,'a'},{101,'b'}};
struct test y[2];
fd=open("./file2",O_RDWR);
int n_write=write(fd,&x,sizeof(struct test)*2);
lseek(fd,0,SEEK_SET);
int n_read=read(fd,&y,sizeof(struct test)*2);
printf("read:%d,%c\n",y[0].a,y[0].b);
printf("read:%d,%c\n",y[1].a,y[1].b);
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/40c3a938c893689552de90ef19283611.png)
以此类推,也可以将链表等写入到文件中
标准C库打开创建文件读写光标移动
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char readBuf[1024]={0};
char *str="write file";
fp=fopen("./file1","w+");
fwrite(str,sizeof(char),strlen(str),fp);
fseek(fp,0,SEEK_SET);
fread(readBuf,sizeof(char),strlen(str),fp);
printf("read data: %s\n",readBuf);
fclose(fp);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/ab1b80f72a3526adf7bcad6d2daf658f.png)