《Linux系统编程篇》文件基础编程 ——基础篇

7 篇文章 0 订阅 ¥159.90 ¥99.00

引言

上节课我们知道了,什么是文件的权限,以及如何去修改文件的权限,这节课,我们将带着大家一起使用Linux系统里面的API来操作文件,一起跟着笔者的步伐走起~

纸上得来终觉浅,绝知此事要躬行 ——陆游

基本的文件操作函数介绍

在Linux系统编程中,我们先来看基本的API,理解基本的文件操作函数是非常重要的。

这节我们带着大家一起进入文件编程。

文件我们想到无非就三个操作,1、打开文件,2、操作文件内容,3、关闭文件

大象装进冰箱?是的,就是这么简单。

于是乎,我们如何装进这个大象是我们学习的关键,用什么工具去打开冰箱(文件),如何把大象放进去(操作文件内容),放进去关冰箱(释放文件)

我们在Linux系统上,当然用的是Linux系统的API,来操作系统的文件了,Linux系统给我们提供哪些工具呢?

下面我列举了一些。可以先看一下,大致熟悉一下open

1、open():打开一个文件

open()函数通常用于打开文件。其原型通常位于<fcntl.h>头文件中
原型如下所示:

#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
  • 第一个原型是用于打开已存在文件的,第二个原型是用于创建新文件的。

  • pathname参数是一个指向要打开的文件的路径名的指针。

  • flags参数指定了打开文件的方式,比如只读、只写、读写等。常见的标志包括O_RDONLYO_WRONLYO_RDWR等。

  • mode参数用于指定新文件的权限,通常用于创建文件时。比如0644表示文件所有者可读写,其他用户只读。

  • mode 是新创建文件的权限,通常与 O_CREAT 标志一起使用。

  • 返回值:成功时返回文件描述符(非负整数),失败时返回 -1。

2、close():关闭一个文件

close() 函数用于关闭一个先前打开的文件。下面是 close() 函数的原型和说明:

#include <unistd.h>

int close(int fd);
  • fd 是之前使用 open() 或其他文件操作函数返回的文件描述符。通过关闭文件描述符,可以释放系统资源并确保文件的正确关闭。

  • 返回值:如果成功关闭文件,则返回值为 0。如果出现错误,返回值为 -1。

3、read():读取文件内容

read() 函数用于从已打开文件中读取数据。下面是 read() 函数的原型和说明:

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
  • fd 是之前使用 open() 打开文件返回的文件描述符。

  • buf 是一个指向存储读取数据的缓冲区的指针。

  • count 是要读取的字节数。

  • 返回值:成功时返回实际读取的字节数,如果到达文件末尾则返回 0,出现错误时返回 -1。

4、write():写入文件内容

write() 函数用于向文件中写入数据。下面是 write() 函数的原型和说明:

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);
  • fd 是之前使用 open() 打开文件返回的文件描述符。

  • buf 是一个指向要写入的数据的缓冲区的指针。

  • count 是要写入的字节数。

  • 返回值:成功时返回实际写入的字节数,出现错误时返回 -1。

5、lseek():在文件中定位

lseek() 函数在Linux系统中用于设置文件偏移量,即移动文件描述符的读写位置。下面是 lseek() 函数的原型和说明:

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
  • fd 是之前使用 open() 打开文件返回的文件描述符。

  • offset 是要移动的偏移量,可以为正数、负数或零。

  • whence 用于指定偏移量的基准位置,可以是 SEEK_SETSEEK_CURSEEK_END。具体含义如下:

    • SEEK_SET:从文件开头开始偏移。

    • SEEK_CUR:从当前文件位置开始偏移。

    • SEEK_END:从文件末尾开始偏移。

  • 返回值:返回新的文件偏移量,若出现错误返回 -1。

6、unlink():删除文件

unlink() 函数用于删除一个文件的目录项(文件名),并减少该文件的链接数。如果链接数变为零,则文件的数据块将被释放。下面是 unlink() 函数的原型和说明:

#include <unistd.h>

int unlink(const char *pathname);

pathname 是要删除的文件的路径名。

  • 返回值:成功时返回 0,失败时返回 -1。

小节(man 手册)

就只有这些个操作函数吗?不,不是的,后面可能会遇到新的接口,接触自己认知以外的函数,我们遇到这些应该怎么办,不要慌,我告诉你怎么办。

在Linux系统编程当中,当我们使用了系统的接口,那么我们可以使用Linux自带的手册看接口如何使用,我们可以使用man
open来直接看linux对这些API的解释,以及他所需的头文件。比如:

bash man open

或者

bash man 2 open
在这里插入图片描述
总之,建议找不到函数的时候多看这个man手册,他里面都是有结构规律的,只需要找我们需要的东西就好,不用抠字眼一个一个去通读。

实操实例

实现功能:两个文件,demo1.c 以及 demo2.c

  • demo1.c创建文件
  • demo2.c删除文件

demo1.c创建文件

使用open创建一个文件,使用write向里面写入一段话“hello Linux,i im jiaju(Strange_Head) I’m coming.”,然后读取(read)全部的内容,打印到命令行,然后再次使用write尾部追加写入,“家驹很帅,梦想很近”,”-------------------------“,最后操作完成,使用close关闭文件.

注意,容易混的地方是lseek(将他理解为编辑文件时候的光标),初学者请慢慢理解下面的代码,附带详细注释。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>


int main()
{
        //创建一个fd用作文件描述符
        int fd = -1;

        //我们直接创建文件,使用三个参数的open
        //使用相对路径
        //权限为可读可写O_RDWR,使用创建文件的宏O_CREAT
        //文件权限,644
        //int open(const char *pathname, int flags, mode_t mode);
        fd = open("./家驹很帅.txt",O_RDWR | O_CREAT,644);

        if(fd == -1) {
                printf("文件创建或打开失败\n");
                return -1;
        }


        //写入操作
        //ssize_t write(int fd, const void *buf, size_t count);
        char write_buffer[100];
        memset(write_buffer,'\0',sizeof(write_buffer));
        strncpy(write_buffer,"hello Linux,i im jiaju(Strange_Head) I’m coming.\n",sizeof("hello Linux,i im jiaju(Strange_Head) I’m coming.\n"));
        write(fd,write_buffer,sizeof(write_buffer));

        //使用lseek计算文件大小
        //
        //将lseek理解为光标,就像windows里面闪烁的光标
        //如果通过sleek计算大小,我们先将光标置为文件开头,然后在移到末尾,中间偏移了多少字节既是文件大小
        //off_t lseek(int fd, off_t offset, int whence);
        lseek(fd,0,SEEK_SET);
        int file_size = lseek(fd,0,SEEK_END);
        lseek(fd,0,SEEK_SET);   //得到文件大小需要再从头开始,因为后面read是从当前光标开始的


        //读取操作
        //ssize_t read(int fd, void *buf, size_t count);
        char read_buffer[100];
        memset(read_buffer,0,sizeof(read_buffer));
        read(fd,read_buffer,sizeof(read_buffer));

        //打印得到的字符串
        printf("%s\n",read_buffer);

        //注意,此时lseek的光标在文件末尾。
        //
        //我们接着追加内容
        memset(write_buffer,'\0',sizeof(write_buffer));
		strncpy(write_buffer,"\n家驹很帅,梦想很近\n",sizeof("\n家驹很帅,梦想很近\n"));
        write(fd,write_buffer,sizeof(write_buffer));

 		//插入横杠
        memset(write_buffer,'\0',sizeof(write_buffer));
        strncpy(write_buffer,"\n-----------------------------------\n",sizeof("\n-----------------------------------\n"));
        write(fd,write_buffer,sizeof(write_buffer));


        //关闭文件
        close(fd);


        return 0;
}

在这里插入图片描述

demo2.c删除文件(手动制作rm命令)

直接调用unlink删除文件。
我们直接调用这个命令删除一个的固定文件,感觉不爽,既然要删除文件,如果我能指定就好了,直接做一个低配版的rm命令!
使用argc,argv的特性,轻松完成

#include <stdio.h>
#include <unistd.h>


int main(int argc,char **argv)
{

        if(argc==2){
                int i  = 0;
                for(i = 0;i < argc;i++){
                printf("argv[%d]%s\n",i,argv[i]);
                }


                if(unlink(argv[1])<0){
                        printf("\n删除失败\n");
                }

        }else{
                printf("参数错误\n");
        }

        return 0;
}

在这里插入图片描述

实例结果展示

在这里插入图片描述
调用demo1.c编译出的./creat,生成家驹很帅.txt

调用demo2.c编译出的./myrm, 删除生成的文件。

拓展

open系列和fopen系列有什么不同

fopen,fread,fwrite,flseek等等……

很多小伙伴可能知道,fopen可以打开文件,他和open有什么不一样呢,明明最终的结果是一样的。

答案:当然不一样,除了多了一个前缀f,还多了很多细节,我们来拓展一下。

  1. open 函数是一个系统调用,而 fopen 函数是C标准库提供的函数。

  2. open 函数是低级别的函数,提供了更多的控制和自由度,可以指定文件的打开模式(读、写、追加等)、权限等。fopen 函数则是高级别函数,通常用于简单的文件操作,它提供了一种更简单的接口,隐藏了一些底层细节。

  3. open 函数返回一个文件描述符(file descriptor),而 fopen 函数返回一个 FILE* 类型的指针。文件描述符是一个整数,用于标识已打开的文件,而 FILE* 是一个指向 FILE
    结构体的指针,该结构体包含了文件流的信息。

  4. 使用 open 函数打开文件后,通常需要使用 readwrite 等系统调用来进行读写操作;而使用 fopen 函数打开文件后,可以使用 fprintffscanf 等标准库函数来进行读写操作。

  5. open 函数是Unix标准的一部分,而 fopen 函数是C标准库的一部分。

  6. fopen有缓冲区,open没有

无论是使用open,还是fopen,看个人喜好,已经代码编程习惯,我是倾向于open系列的。

结束

今天的学习就到这里了,唯手熟尔,我这里实现了一个rm功能,是不是可以自己想一想,实现一个cp自己的拷贝命令呢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Strange_Head

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值