Linux系统编程

文章目录

Linux文件开发

查看Linux用户手册

man + 关键字
man 2 open打开用户手册中的第2页的open函数那一章

文件的打开与创建open函数

包含头文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

函数描述

在这里插入图片描述
file descriptor文件描述符
call调用
给一个文件的路径,返回一个文件描述符,它是一个小的非负整数用在后续的系统调用中。文件打开成功返回非负整数,打开失败返回-1
在这里插入图片描述

查看文件权限

ls -lrw可读写;x可执行
在这里插入图片描述
open函数中的mode权限:
在这里插入图片描述
可读可写就是0400+0200=0600

用法

  1. 正常打开一个文件:新建一个file1文件,在当前文件夹内新建file1.c输入如下代码
  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 
  6 int main()
  7 {
  8     int fd;
  9     fd = open("./file1",O_RDWR);
 10     printf("fd = %d\n",fd);
 11     return 0;
 12 }
//fd = 3
  1. 如果文件不存在则创建文件并打开:删除file1文件,在当前文件夹内新建file1.c输入如下代码
 1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 
  6 int main()
  7 {
  8     int fd;
  9     fd = open("./file1",O_RDWR);
 10     if(fd = -1)
 11     {
 12         printf("file doesn't exist!\n");
 13         fd = open("./file1",O_RDWR|O_CREAT,00600);
 14         if(fd > 0)
 15         {
 16             printf("create file successfully!\n");
 17         }
 18     }
 19     printf("fd = %d\n",fd);
 20     return 0;
 21 }
//file doesn't exist!
//create file successfully!
//fd = 3

文件写入操作编程write函数

write函数描述

在这里插入图片描述
write函数从buf缓冲区向文件描述符fd指代的文件中写入count大小的数据。
如果写入成功,返回写入数据的大小(0代表没东西被写入),-1表示有错误。

包含头文件

#include <unistd.h>

close函数

在这里插入图片描述
写入文件内容后用close函数关闭文件

用法

如果file1文件不存在则先创建,再写入12345678901234567890,最后关闭文件file1

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 
  8 int main()
  9 {
 10     int fd;
 11     fd = open("./file1",O_RDWR);
 12     if(fd = -1)
 13     {
 14         printf("file doesn't exist!\n");
 15         fd = open("./file1",O_RDWR|O_CREAT,00600);
 16         if(fd > 0)
 17         {
 18             printf("create file successfully!\n");
 19         }
 20     }
 21     printf("open file successfully!\n",fd);
 22     char *buf = "12345678901234567890";
 23     write(fd,buf,strlen(buf)*sizeof(char));
 24     close(fd);
 25     return 0;
 26 }

文件读取操作read函数

函数描述

在这里插入图片描述
函数会从文件描述符fd所在的文件中读取count个字节大小的数据到buf缓冲区内。
读取成功返回读取的字节大小,失败返回-1

包含头文件

#include <unistd.h>

用法

读取写入file1文件的数据,读取时采用重新打开文件让光标定位到数据开头

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 #include <stdlib.h>
  8 
  9 int main()
 10 {
 11     int fd;
 12     fd = open("./file1",O_RDWR);
 13     if(fd = -1)
 14     {
 15         printf("file doesn't exist!\n");
 16         fd = open("./file1",O_RDWR|O_CREAT,00600);
 17         if(fd > 0)
 18         {
 19             printf("create file successfully!\n");
 20         }
 21     }
 22     printf("open file successfully!\n",fd);
 23     char *buf = "12345678901234567890";
 24     int n_write;
 25     n_write = write(fd,buf,strlen(buf)*sizeof(char));
 26     close(fd);
 27     fd = open("./file1",O_RDWR|O_CREAT,00600);
 28     if(n_write != -1)
 29     {
 30         printf("write %d bytes to file1\n",n_write);
 31     }
 32     int n_read;
 33     char *readBuf = (char *)malloc(n_write);
 34     n_read = read(fd,readBuf,n_write);
 35     printf("read %d bytes,context is:%s\n",n_read,readBuf);
 36     return 0;
 37 }

文件光标移动操作lseek函数

函数描述

在这里插入图片描述
函数是用来重新定位打开的文件的光标的。
SEEK_SET光标在数据头部位置
SEEK_CUR光标在数据当前位置
SEEK_END光标在数据尾部位置
offset设置光标向右偏移字节大小,向左偏移为负数
在这里插入图片描述
读取成功返回从文件开始的偏移字节大小,读取失败返回-1

包含头文件

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

用法

  1. 打开文件并写入数据后,将光标重新定位至数据头部,读取数据
  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 #include <stdlib.h>
  8 
  9 int main()
 10 {
 11     int fd;
 12     fd = open("./file1",O_RDWR);
 13     if(fd = -1)
 14     {
 15         printf("file doesn't exist!\n");
 16         fd = open("./file1",O_RDWR|O_CREAT,00600);
 17         if(fd > 0)
 18         {
 19             printf("create file successfully!\n");
 20         }
 21     }
 22     printf("open file successfully!\n",fd);
 23     char *buf = "12345678901234567890";
 24     int n_write;
 25     n_write = write(fd,buf,strlen(buf)*sizeof(char));
 26     if(n_write != -1)
 27     {
 28         printf("write %d bytes to file1\n",n_write);
 29     }
 30     int n_read;
 31     char *readBuf = (char *)malloc(n_write);
 32     lseek(fd,-n_write,SEEK_END);
 //lseek(fd,0,SEEK_SET); //lseek(fd,-n_write,SEEK_CUR);都可以
 33     n_read = read(fd,readBuf,n_write);
 34     printf("read %d bytes,context is:%s\n",n_read,readBuf);
 35     return 0;
 36 }
  1. 计算文件大小
1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <sys/types.h>
  5 #include <unistd.h>
  6 #include <stdio.h>
  7 
  8 int main()
  9 {
 10     int fd;
 11     fd = open("./file1",O_RDWR);
 12     if(fd == -1)
 13     {
 14         printf("file1 doesn't exist!\n");
 15         fd = open("./file1",O_RDWR|O_CREAT,00600);
 16         printf("create file1 success!\n");
 17     }
 18     printf("open file1 success!");
 19     int fileSize;
 20     fileSize = lseek(fd,0,SEEK_END);
 21     printf("file1's size is %d\n",fileSize);
 22     return 0;
 23 }

因为lseek返回的是从文件开始到光标的偏移字节大小,所以要把光标移动到文件尾部lseek(fd,0,SEEK_END)

文件打开创建补充

在这里插入图片描述

O_EXCL参数描述

如果在open函数内同时写了O_CREAT,如果文件存在则打开失败返回-1

O_EXCL参数的用法

如果文件file1存在则提示文件已存在,如果删除file1重新调用程序,则创建文件

1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 
  6 int main()
  7 {
  8     int fd;
  9     fd = open("./file1",O_RDWR|O_CREAT|O_EXCL,00600);
 10     if(fd == -1)
 11     {
 12         printf("file1 has existed!\n");
 13     }
 14     return 0;
 15 }

O_APPEND参数描述

写入数据时如果首次调用含O_APPEND的open函数则会在文件尾部写入数据

O_APPEND参数的用法

如果用了该参数则在文件尾部写数据,如果没用该参数,写入的新数据会覆盖原来的位置

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 
  8 int main()
  9 {
 10     int fd;
 11     fd = open("./file1",O_RDWR|O_APPEND);
 12     printf("fd = %d\n",fd);
 13     char *buf = "peterpeter";
 14     write(fd,buf,strlen(buf)*sizeof(char));
 15     close(fd);
 16     return 0;
 17 }

O_TRUNC参数描述

如果文件中有内容,将其清空再写入新数据。
注意:在open函数里加了该参数,后面就读取不到内容了,因为被清空了

O_TRUNC参数的用法

 1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 
  8 int main()
  9 {
 10     int fd;
 11     fd = open("./file1",O_RDWR|O_TRUNC);
 12     printf("fd = %d\n",fd);
 13     char *buf = "peterpeter";
 14     write(fd,buf,strlen(buf)*sizeof(char));
 15     close(fd);
 16     return 0;
 17 }

creat函数描述

在这里插入图片描述

creat函数的用法

在当前路径下创建一个名为file2的文件,可读可写可执行

 1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 
  5 int main()
  6 {
  7     creat("./file2",S_IRWXU);
  8     return 0;
  9 }

文件操作原理简述

文件描述符

在这里插入图片描述

标准输入和标准输出

文件描述符(0,1,2)宏STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO代表标准输入、标准输出和标准错误。标准输入就是从键盘读取;标准输出就是从控制台输出

  1 #include <unistd.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 
  5 int main()
  6 {
  7     char *readBuf = (char *)malloc(10);
  8     read(STDIN_FILENO,readBuf,10);
  9     write(STDOUT_FILENO,readBuf,10);
 10     printf("done!\n");
 11     return 0;
 12 }   
从键盘输入//sdfs
//sdfs
//done!

从键盘读取10个字节到readBuf缓冲区,再从readBuf缓冲区写到控制台10个字节,所以这里都是readBuf

操作文件的步骤

在这里插入图片描述
静态文件存在块设备中 -> 调用open -> 在linux内核申请内存(动态内存)用一个数据结构储存 -> 读写 -> 调用close -> linux内核中的动态内存更新块设备中的静态文件

文件操作应用——实现cp命令

main函数的参数

main函数的参数从第一个指令开始

  1 #include <stdio.h>
  2 
  3 int main(int argc,char **argv)
  4 {
  5     printf("number of argc is:%d\n",argc);
  6     printf("No.1 param is:%s\n",argv[0]);
  7     printf("No.2 param is:%s\n",argv[1]);
  8     printf("No.3 param is:%s\n",argv[2]);
  9     return 0;
 10 }

在这里插入图片描述

编程实现

思路:
打开src.c
读src.c中的数据到readBuf
打开/创建des.c
将readBuf写入des.c,如果des.c不存在则创建,如果des.c存在,写入前清空其内容
关闭两个文件

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <stdio.h>
  8 
  9 int main(int argc,char **argv)
 10 {
 11     if(argc != 3)
 12     {
 13         printf("param error!\n");
 14         exit(-1);
 15     }
 16     int fdSrc;
 17     fdSrc = open(argv[1],O_RDWR);
 18     int fileSize = lseek(fdSrc,0,SEEK_END);
 19     lseek(fdSrc,0,SEEK_SET);
 20     char *readBuf = (char *)malloc(sizeof(char)*fileSize);
 21     read(fdSrc,readBuf,fileSize);
 22     int fdDes;
 23     fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,00600);
 24     write(fdDes,readBuf,strlen(readBuf)*sizeof(char));
 25     close(fdSrc);
 26     close(fdDes);
 27     return 0;
 28 }
 //gcc mycp.c -o mycp
//./mycp file1 file2
//file1被复制成file2

perror()函数打印错误信息

调用perror函数后程序会自动结束

文件编程应用——修改程序的配置文件

思路:
打开文件
读取文件到readBuf缓冲区
用strstr()查找目标字符串
指针定位到目标数据位置并修改数据
将readBuf写入原文件
关闭文件
以下代码只能修改1位数字

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <stdio.h>
  8 
  9 int main(int argc,char **argv)
 10 {
 11     if(argc != 2)
 12     {
 13         printf("param error!\n");
 14         exit(-1);
 15     }
 16     int fd;
 17     fd = open(argv[1],O_RDWR);
 18     int fileSize = lseek(fd,0,SEEK_END);
 19     lseek(fd,0,SEEK_SET);
 20     char *readBuf = (char *)malloc(sizeof(char)*fileSize + 1);
 21     read(fd,readBuf,fileSize);
 22     char *p = strstr(readBuf,"WIDTH = ");
 23     if(p == NULL)
 24     {
 25         printf("not found!\n");
 26         exit(-1);
 27     }
 28     p = p + strlen("WIDTH = ");
 29     *p = '8';
 30 /*  while(++p != NULL)
 31     {
 32         if(*p == '\0')
 33         {
 34             break;
 35         }
 36         *p = '\0';
 37     }*/
 38     lseek(fd,0,SEEK_SET);
 39     write(fd,readBuf,fileSize);
 40     close(fd);
 41     return 0;
 42 }
 //gcc changeConfig.c -o changeConfig
 //./changeConfig test.config
 WIDTH修改为8

写除了字符串类型到文件

写一个整数到文件

write()和read()函数中的参数类型是const void * 所以不一定要是char * 类型

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include <stdio.h>
  6 
  7 int main()
  8 {
  9     int fd;
 10     fd = open("./file1",O_RDWR);
 11     int data = 10;
 12     write(fd,&data,sizeof(int));
 13     lseek(fd,0,SEEK_SET);
 14     int data2;
 15     read(fd,&data2,sizeof(int));
 16     printf("read:%d\n",data2);
 17     close(fd);
 18     return 0;
 19 }

写一个结构体到文件

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include <stdio.h>
  6 
  7 typedef struct node
  8 {
  9     int a;
 10     char c;
 11 }Node;
 12 
 13 int main()
 14 {
 15     int fd;
 16     fd = open("./file1",O_RDWR);
 17     Node node1 = {1,'g'};
 18     write(fd,&node1,sizeof(Node));
 19     lseek(fd,0,SEEK_SET);
 20     Node node2;
 21     read(fd,&node2,sizeof(Node));
 22     printf("read:%d,%c\n",node2.a,node2.c);
 23     close(fd);
 24     return 0;
 25 }

写一个结构体数组到文件

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include <stdio.h>
  6 
  7 typedef struct node
  8 {
  9     int a;
 10     char c;
 11 }Node;
 12 
 13 int main()
 14 {
 15     int fd;
 16     fd = open("./file1",O_RDWR);
 17     Node node1[2] = {
  {1,'g'},{2,'h'}};
 18     write(fd,&node1,sizeof(Node)*2);
 19     lseek(fd,0,SEEK_SET);
 20     Node node2[2];
 21     read(fd,&node2,sizeof(Node)*2);
 22     printf("read:%d,%c\n",node2[0].a,node2[0].c);
 23     printf("read:%d,%c\n",node2[1].a,node2[1].c);
 24     close(fd);
 25     return 0;
 26 }

open和fopen的区别

总结open与fopen的区别

  1. 来源不同
    open是Unix系统调用函数。fopen的C语言库函数。

  2. 移植性不同
    fopen移植性更好,能在更多系统中调用。

  3. 适用范围不同
    fopen用来操作普通文件。open主要用于linux系统。

  4. 缓冲
    fopen是在缓冲区操作文件,效率更高。open是通过用户态和内核态切换操作文件。但现在的机器这点效率忽略不计。

标准C库操作文件

fopen()函数描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
fopen()函数用来打开文件。传入path文件路径,mode打开的文件权限,mode是字符串指针 。权限如第二张图,w+表示不存在就创建文件。成功调用该函数返回FILE的指针,有错返回NULL

fwrite()和fread()函数描述

在这里插入图片描述
fwrite()函数用来向文件写入数据。它从ptr缓冲区获取nmemb数量每个size字节大小的数据写入stream指向的文件流。

fread()函数用来读取数据。它从stream指向的文件流中读取nmemb数量每个size字节大小的数据储存到ptr缓冲区中。

fwrite()和fread()返回成功写入或读取的项目数量,如果调用出错返回很小的项目数量或0。它们的返回值取决于第三个参数nmemb
如果fwrite的nmemb参数写的很大,会将乱码写入目标文件,如下图:
在这里插入图片描述
如果fread的nmemb参数写的很大,没有问题

fseek()函数描述

在这里插入图片描述
在这里插入图片描述
fseek用来操作文件中的光标位置。参数和lseek用法相同。成功调用返回0,失败返回-1。

用法

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 int main()
  6 {
  7     FILE *fp;
  8     fp = fopen("./file1","w+");
  9     char *str = "hello world!";
 10     int n_write = fwrite(str,sizeof(char),strlen(str),fp);
 11     fseek(fp,0,SEEK_SET);
 12     char *readBuf = (char *)malloc(20);
 13     int n_read = fread(readBuf,sizeof(char),strlen(str),fp);
 14     printf("read:%s\n",readBuf);
 15     printf("n_write = %d\n",n_write);
 16     printf("n_read = %d\n",n_read);
 17     return 0;
 18 }
//read:hello world!
//n_write = 12
//n_read = 12

如果写入的数据数量大于字符数量,比如fwrite(str,sizeof(char),20,fp);会在file1中多写入其它字符造成错误

写入结构体

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 typedef struct Node
  6 {
  7     int num;
  8     char name;
  9 }Node;
 10 int main()
 11 {
 12     Node data1 = {100,'a'};
 13     FILE *fp;
 14     fp = fopen("./file1","w+");
 15     int nwrite = fwrite(&data1,sizeof(Node),1,fp);
 16     Node data2;
 17     fseek(fp,0,SEEK_SET);
 18     int nread = fread(&data2,sizeof(Node),1,fp);
 19     printf("read:num = %d\tname = %c\n",data2.num,data2.name);
 20     printf("write:%d\tread:%d\n",nwrite,nread);
 21     fclose(fp);
 22     return 0;
 23 }
//read:num = 100    name = a
//write:1   read:1

fputc()函数描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
fputc()函数将参数c强制转换成无符号字符,写入stream文件流
返回被写入的无符号字符强转成整型的整数,失败返回EOF

用法

将字符串写入file1文件中

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 int main()
  5 {
  6     FILE *fp;
  7     fp = fopen("./file1","w+");
  8     char *str = "hello world!";
  9     int i;
 10     int len = strlen(str);
 11     int a;
 12     for(i = 0; i < len; i++)
 13     {
 14         a = fputc(*str,fp);
 15         str++;
 16         printf("fputc = %d\n",a);
 17     }
 18     fclose(fp);
 19     return 0;
 20 }
注意这里for循环中要将len提前赋值,因为如果写成i < strlen(str),随着每次循环str++,strlen(str)的值也会随之变化

fgetc()和feof()函数描述

在这里插入图片描述
在这里插入图片描述
fgetc()函数从stream文件流中读取一个字符,将其转换成无符号字符并强转成整型输出,返回EOF时有错误<

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值