Linux系统编程------文件编程

目录

1.文件编程概述

2.文件打开及创建

2.1 API函数:open函数

使用示例

1.包含头文件:

2.函数原型:

1.参数解释

2.2 打开文件(open关键:返回文件描述符)

2.3 创建并且打开文件(O_CREAT)

 2.4 O_EXCL可用来判断文件是否存在(配合O_CREAT使用)

2.5 O_APPEND

2.6 O_TRUNC(擦除原有内容,重新写入)

2.7 creat创建文件

3.文件--写入操作编程

3.1 写入文件

4.文件--读操作编程

阅读函数,光标移动

5.文件编程应用

5.1文件操作小应用之实现cp指令

5.2文件编程修改程序的配置文件


目录大纲:

1.文件编程概述

        本节是Linux下对文件进行的相关编程。也就是操作相关API对文件进行操作。

        涉及到的API:(open;read;write;)

2.文件打开及创建

2.1 API函数:open函数

这个函数定义在 POSIX 标准中,通常在 Unix-like 系统的 <fcntl.h> 头文件中声明。

可以在Linux下查看函数基本信息(cmd:man 2 open)进行使用。

使用示例

1.包含头文件:
#include <sys/types.h>          // 引入系统类型定义,如打开文件所需的文件描述符类型
#include <sys/stat.h>           // 引入用于获取文件状态的函数和宏
#include <fcntl.h>              // 引入文件操作相关的函数,如open()
2.函数原型:
1.int open(const char *pathname, int flags);
2.int open(const char *pathname, int flags, mode_t mode);
3.int creat(const char *pathname, mode_t mode);
open()返回一个文件描述符

int open(const char *pathname, int flags, mode_t mode);打开/创建一个新的文件,返回值类型为整形(

  • 成功时,open 函数返回一个新的文件描述符,这是一个非负整数,用于以后对文件的读写操作。

  • 出错时,返回 -1,并设置全局变量 errno 来指示错误类型。

)。


1.参数解释

1.const char *pathname:指针(指向字符串),该字符串包含打开/创建的文件的路径名;             pathname就是路径名(绝对路径、相对路径都可以)。

2.int flags:整数;flags表示如何打开文件、对文件的访问类型。                

  • 它可以是以下值的组合(通过按位或操作 |):

    • O_RDONLY:只读打开。

    • O_WRONLY:只写打开。

    • O_RDWR:读写打开。

      以上三个常数中一般使用一个,下列常数是可选择的。

    • O_APPEND:写入时追加到文件末尾。 (从尾端写入)

    • O_CREAT:如果文件不存在,则创建它。

    • O_EXCL:与 O_CREAT 一起使用,如果文件已存在则返回错误。

    • O_TRUNC:如果文件已存在,则截断它(即清空文件内容)。

    • O_NONBLOCKO_NDELAY:以非阻塞模式打开文件。

    • 还有很多其他标志,具体请参考系统手册。

3.mode_t modemode_t类型;这个参数仅在设置了 O_CREAT 标志时才有意义,它指定了如果需要创建文件时,文件的权限模式(权限模式通常是一个八进制数,例如 0644,表示文件所有者具有读写权限(6),而组用户和其他用户具有只读权限 )。


2.2 打开文件(open关键:返回文件描述符)

#include <sys/types.h>          // 引入系统类型定义,如打开文件所需的文件描述符类型
#include <sys/stat.h>           // 引入用于获取文件状态的函数和宏
#include <fcntl.h>              // 引入文件操作相关的函数,如open()
#include <stdio.h>              // 引入标准输入输出库,用于打印信息

int main()                      // 程序的主函数
{
  int fd;                  // 定义一个整数变量fd,用于存储文件描述符
  fd = open("./file1", O_RDWR);  // 调用open()函数,尝试以读写模式打开./file1文件
                               // O_RDWR标志表示可以读取和写入文件

  printf("fd = %d\\n", fd);  // 如果open()成功,打印文件描述符fd的值
  return 0;                 // 程序正常退出,返回0
}

2.3 创建并且打开文件(O_CREAT)

#include <sys/types.h>          // 引入系统类型定义,如文件描述符类型等
#include <sys/stat.h>           // 引入文件状态相关的宏和结构体定义
#include <fcntl.h>              // 引入文件控制选项,如open()函数和标志位
#include <stdio.h>              // 引入标准输入输出库,用于打印信息

int main()                      // 程序的主函数
{
  int fd;                  // 定义一个整数变量fd,用于存储文件描述符

  // 尝试以读写模式打开当前目录下的file1文件
  fd = open("./file1", O_RDWR); 

  // 检查open()函数的返回值,如果返回-1表示打开文件失败
  if(fd == -1){
          printf("open file1 failed.\\n"); // 打印错误信息
  }

  // 如果第一次打开失败,尝试以读写模式创建文件(如果不存在)并设置权限为600(-rw-------)
  // O_CREAT标志表示如果文件不存在则创建,第三个参数是文件的权限
  fd = open("./file1", O_RDWR|O_CREAT, 0600); 

  // 打印文件描述符的值,无论打开成功与否
  printf("fd = %d\\n", fd); 

  // 程序结束,但请注意,这里没有关闭文件描述符,实际使用中应该在返回前关闭
  return 0; 
}

使用命令查看我们创建的文件,

ammy@jammy-virtual-machine:~/File programming$ ls -l
total 24
-rwxrwxr-x 1 jammy jammy 16048  4月 17 20:21 a.out
-rw-rw-r-- 1 jammy jammy   175  4月 17 19:58 demo1.c
-rw-rw-r-- 1 jammy jammy   326  4月 17 20:20 demo2.c
-rw------- 1 jammy jammy     0  4月 17 20:21 file1

 


 2.4 O_EXCL可用来判断文件是否存在(配合O_CREAT使用)

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


int main()
{
        int fd;
        fd = open("./file1",O_RDWR|O_CREAT|O_EXCL);// O_EXCL判断文件是否存在
        if(fd == -1){
                printf("create file1 failed\n");

        }
        return 0;
}

2.5 O_APPEND

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR|O_APPEND);	//O_APPEND在文件末尾后添加内容

        int n_write  = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write sizeof:%d\n ",n_write);

        }
        lseek(fd,0,SEEK_SET);
        char *readbuf;
        readbuf = (char *)malloc(sizeof(char) * n_write);
        int n_read = read(fd,readbuf,100);
        printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
        close(fd);
        return 0;
}

程序运行前:                                                                                            程序运行后:

      

 若不加O_APPEND:会覆盖原有内容:

2.6 O_TRUNC(擦除原有内容,重新写入)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR|O_TRUNC);//O_TRUNC(擦除原有内容,重新写入)

        int n_write  = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write sizeof:%d\n ",n_write);

        }
        lseek(fd,0,SEEK_SET);
        char *readbuf;	//野指针
        readbuf = (char *)malloc(sizeof(char) * n_write);//开辟空间
        int n_read = read(fd,readbuf,100);
        printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
        close(fd);
        return 0;
}

程序运行前:                                                                                            程序运行后:

               

2.7 creat创建文件

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


int main()
{
        int fd;
        fd = creat("./file2",S_IRWXU);//S_IRWXU 可读可写可执行

        return 0;
}

查询为:  

3.文件--写入操作编程

3.1 写入文件

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <unistd.h>  // 注意这里重复包含了 <unistd.h>
 #include <string.h>
 ​
 // main 函数是程序的入口点
 int main()
 {
  int fd;  // 定义一个文件描述符变量 fd
  char *buf="jammy very handsome";  // 定义一个指向字符串常量的指针 buf
 ​
  // 尝试以读/写模式打开文件 ./file1
  fd = open("./file1", O_RDWR);
 ​
  // 检查文件是否成功打开(如果返回 -1 表示失败)
  if(fd == -1){
      printf("open file1 failed.\\n");  // 打印错误信息
  }
 ​
  // 再次尝试打开文件,如果文件不存在则创建它,并设置权限为 0600
  // 注意:这里有一个逻辑错误,因为之前已经尝试打开过文件,但没有关闭它
  // 如果文件不存在,这里应该不会创建文件,因为 O_CREAT 标志没有设置
  fd = open("./file1", O_RDWR|O_CREAT, 0600);
  printf("fd = %d\\n",fd);  // 打印文件描述符的值
 ​
  // 检查文件描述符是否有效(大于 0 表示成功)
  if(fd > 0){
      printf("create file1 success\\n");  // 打印成功创建文件的信息
  }
 ​
  // 使用 write 函数将字符串 buf 写入到文件描述符 fd 指向的文件中
  // 注意:这里没有检查 write 的返回值来判断是否写入成功
  write(fd,buf,strlen(buf));  // strlen 获取字符串的长度
 ​
  // 关闭文件描述符 fd,释放资源
  close(fd);
 ​
  // main 函数返回 0,表示程序成功执行
  return 0;
 }

4.文件--读操作编程

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 ​
 ​
 int main()
 {
      int fd;
      char *buf="jammy very handsome";
      fd = open("./file1",O_RDWR);
 ​
      if(fd == -1){
              printf("open file1 failed.\n");
      }
 ​
 ​
      fd = open("./file1",O_RDWR|O_CREAT,0600);
      printf("fd = %d\n",fd);
 ​
      if(fd > 0){
              printf("create file1 success\n");
      }
 ​
      //ssize_t write(int fd, const void *buf, size_t count);
      int n_write = write(fd,buf,strlen(buf));
      //size_t strlen(const char *s);
 ​
      if(n_write != -1){
              printf("write %d byte to file1\n",n_write);
      }
 ​
      close(fd);  // 关闭文件描述符 fd
      fd = open("./file1",O_RDWR); // 再次打开文件以读取内容//用于刷新光标
 ​
      char *readBuf;
      readBuf = (char *)malloc(sizeof(char)*n_write);
      //ssize_t read(int fd, void *buf, size_t count);
      int n_read = read(fd,readBuf,n_write);
 ​
      printf("read:%d,context:%s\n",n_read,readBuf);
 ​
 ​
 ​
      //int close(int fd);
      close(fd);
 ​
      return 0;
 }
 ~            
阅读函数,光标移动

lseek 系统调用在 Unix-like 系统中用于改变文件的读/写位置。该函数的原型定义在 <unistd.h> 头文件中。函数的三个参数分别是:

  1. fd:文件描述符,它是之前通过 open 系统调用返回的。

  2. offset:要移动的偏移量,以字节为单位。

  3. whence:指定 offset 的基准位置,它可以是以下三个值之一:

    • SEEK_SET:偏移量基于文件的开头(即文件偏移量为 0 的位置)。

    • SEEK_CUR:偏移量基于当前文件位置。

    • SEEK_END:偏移量基于文件末尾。

whenceSEEK_SET 时,lseek 会将文件位置指针设置为 offset 指定的位置。如果 offset 为 0,文件位置指针将被设置为文件的开头。

以下是对 lseek(fd,0,SEEK_SET); 这行代码的注释:

 lseek(fd, 0, SEEK_SET);
 // 将文件描述符为 fd 的文件的读/写位置设置为文件的开头。
 // 偏移量为 0 表示文件开头,这是文件流的位置被重置为开始位置。

这行代码通常用在读取或写入文件之前,以确保文件位置指针位于正确的位置。例如,如果你想从文件的开头开始读取或写入,你可能会在调用 readwrite 之前调用 lseek

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 ​
 ​
 int main()
 {
      int fd;
      char *buf="jammy very handsome";
      fd = open("./file1",O_RDWR);
 ​
      if(fd == -1){
              printf("open file1 failed.\n");
      }
 ​
 ​
      fd = open("./file1",O_RDWR|O_CREAT,0600);
      printf("fd = %d\n",fd);
 ​
      if(fd > 0){
              printf("create file1 success\n");
      }
 ​
      //ssize_t write(int fd, const void *buf, size_t count);
      int n_write = write(fd,buf,strlen(buf));
      //size_t strlen(const char *s);
 ​
      if(n_write != -1){
              printf("write %d byte to file1\n",n_write);
      }
 ​
     // close(fd);  // 关闭文件描述符 fd
      //fd = open("./file1",O_RDWR); // 再次打开文件以读取内容//用于刷新光标
         lseek(fd, 0, SEEK_SET);  //移动光标到开头
      char *readBuf;
      readBuf = (char *)malloc(sizeof(char)*n_write);
      //ssize_t read(int fd, void *buf, size_t count);
      int n_read = read(fd,readBuf,n_write);
 ​
      printf("read:%d,context:%s\n",n_read,readBuf);
 ​
 ​
 ​
      //int close(int fd);
      close(fd);
 ​
      return 0;
 }

5.文件编程应用

5.1文件操作小应用之实现cp指令

这段代码是一个简单的C程序,它接收命令行参数,并打印出传递给程序的参数数量以及前三个参数的内容。

以下是代码的详细解释和注释:

#include <stdio.h>

这是预处理指令,它告诉编译器包含标准输入输出头文件 stdio.h,该头文件包含了 printf 函数等标准I/O函数的定义。

int main(int argc, char **argv)

这是主函数 main 的声明。main 函数是每个C程序的入口点。

参数解释:

  • int argc:这是一个整数参数,表示传递给程序的命令行参数的数量(argument count)。

  • char **argv:这是一个指向字符串数组的指针,该数组包含了所有的命令行参数(argument vector)。每个参数都是一个以 null 结尾的字符串。

以下是 main 函数体的详细注释:

 {
     // 打印传递给程序的总参数数量
     printf("total params :%d\n", 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]);
 ​
     // 程序正常退出,返回0
     return 0;
 }

以下是每行的详细注释:

  • printf("total params :%d\n", argc);:这行代码使用 printf 函数打印出传递给程序的总参数数量。

  • 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;:这表示程序成功执行并正常退出。在 main 函数中,返回0通常表示程序成功结束。

需要注意的是,如果传递给程序的参数少于3个,尝试访问 argv[1]argv[2] 可能会导致未定义的行为,因为它们可能指向未初始化的内存。在实际的程序中,应该检查 argc 的值,以确保不会尝试访问超出范围的数组元素。

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
 ​
 ​
 int main()
 {
         int fd;
         char *buf="jammy very handsome";
         fd = open("./file1",O_RDWR);
 ​
         if(fd == -1){
                 printf("open file1 failed.\n");
         }
 ​
 ​
         fd = open("./file1",O_RDWR|O_CREAT,0600);
         printf("fd = %d\n",fd);
 ​
         if(fd > 0){
                 printf("create file1 success\n");
         }
 ​
         //ssize_t write(int fd, const void *buf, size_t count);
         int n_write = write(fd,buf,strlen(buf));
         //size_t strlen(const char *s);
 ​
         if(n_write != -1){
                 printf("write %d byte to file1\n",n_write);
         }
 ​
         //off_t lseek(int fd, off_t offset, int whence);
         lseek(fd,0,SEEK_SET);
 ​
         char *readBuf;
         readBuf = (char *)malloc(sizeof(char)*n_write);
         //ssize_t read(int fd, void *buf, size_t count);
         int n_read = read(fd,readBuf,n_write);
 ​
         printf("read:%d,context:%s\n",n_read,readBuf);
 ​
 ​
 ​
         //int close(int fd);
         close(fd);
 ​
         return 0;
 }
     

5.2文件编程修改程序的配置文件

这段代码是一个C程序,它接受一个命令行参数,该参数是源文件的路径。程序的功能是打开这个文件,读取其内容,查找字符串 "LENG=",并将其后的第一个字符替换为 '5',然后将整个内容写回到文件中。

以下是代码的详细解释和注释:

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h>

这些是预处理指令,用于包含程序需要的头文件。

  • <sys/types.h>:包含了系统数据类型定义。

  • <sys/stat.h>:包含了文件状态获取的结构体和函数原型。

  • <fcntl.h>:包含了文件控制选项。

  • <stdio.h>:包含了标准输入输出函数。

  • <unistd.h>:包含了各种unistd库函数的原型,如 readwritelseek 等。

  • <string.h>:包含了字符串处理函数。

  • <stdlib.h>:包含了标准库函数,如 mallocexit

     int main(int argc, char **argv)

这是主函数的声明。

以下是主函数的详细注释:

 {
     int fdSrc; // 源文件的文件描述符
     int fdDes; // 目标文件的文件描述符(在这个程序中没有使用)
 ​
     char *readBuf = NULL; // 用来存储从文件中读取的数据的缓冲区
 ​
     if (argc != 2) { // 检查命令行参数的数量是否为2(程序名+文件名)
         printf("pararm error\n"); // 打印错误信息
         exit(-1); // 非正常退出程序
     }
 ​
     // 打开源文件,以读写方式
     fdSrc = open(argv[1], O_RDWR);
     if (fdSrc == -1) { // 如果打开文件失败,应该检查返回值,这里没有检查,但是实际应用中应该检查
         perror("open source file failed"); // 打印错误信息
         exit(-1); // 非正常退出程序
     }
 ​
     int size = lseek(fdSrc, 0, SEEK_END); // 获取文件的大小
     lseek(fdSrc, 0, SEEK_SET); // 将文件指针移回文件开始位置
 ​
     // 分配足够的空间来存储整个文件内容加上一些额外的空间
     readBuf = (char *)malloc(sizeof(char) * size + 8);
     if (readBuf == NULL) { // 如果分配失败,应该检查返回值
         perror("malloc failed"); // 打印错误信息
         exit(-1); // 非正常退出程序
     }
 ​
     // 从文件中读取数据到缓冲区
     int n_read = read(fdSrc, readBuf, size);
 ​
     // 查找字符串 "LENG="
     char *p = strstr(readBuf, "LENG=");
     if (p == NULL) { // 如果没有找到
         printf("not found\n"); // 打印信息
         exit(-1); // 非正常退出程序
     }
 ​
     // 移动到 "LENG=" 后面的字符
     p = p + strlen("LENG=");
     *p = '5'; // 将找到的字符替换为 '5'
 ​
     // 将文件指针移回文件开始位置
     lseek(fdSrc, 0, SEEK_SET);
     // 将修改后的内容写回到文件中
     int n_write = write(fdSrc, readBuf, strlen(readBuf));
 ​
     // 关闭文件
     close(fdSrc);
 ​
     // 释放分配的内存
     free(readBuf);
 ​
     return 0; // 正常退出程序
 }

注意:

  1. 程序没有处理 readwrite 返回值,实际应用中应该检查这些函数的返回值以处理可能的错误。

  2. 程序没有释放 readBuf 分配的内存,这会导致内存泄漏。在 return 0; 之前应该添加 free(readBuf); 来释放内存。

  3. 程序没有处理文件打开失败的情况,实际应用中应该检查 open 的返回值。

  4. 程序假设 "LENG=" 后面至少有一个字符,如果这个假设不成立,那么 *p = '5'; 可能会导致未定义行为。

  • 49
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值