【系统编程-文件IO】

本文详细介绍了Linux系统编程中的文件IO操作,包括文件描述符的概念、文件的打开与关闭、读写文件、偏移量的操作、阻塞与非阻塞模式以及文件描述符的复制。通过open、close、read、write、lseek等函数的讲解,阐述了文件IO的基本操作和注意事项,并提供了相关的练习题目,帮助读者掌握文件IO的核心技能。
摘要由CSDN通过智能技术生成

文件IO(系统调用)

文件描述符

以文件描述符指代打开的文件,非负整数。一个进程启动之后,默认打开三个文件描述符:

  • 0标准输入 #define STDIN_FILENO
  • 1标准输出 #define STDOUT_FILENO
  • 2标准错误 #define STDERR_FILENO

操作系统为每个进程维护一个文件描述符表,新打开文件返回文件描述符表中未使用的最小文件描述符,调用open函数可以打开或创建一个文件,得到一个文件描述符。
image-20230727105257393

文件的打开与关闭

打开文件

open函数:打开或者新建一个文件函数原型

  • int open(const char *pathname, int flags);
  • int open(const char *pathname, int flags, mode_t mode);

函数参数:

  • pathname:要打开或创建的文件路径

  • flags:文件访问模式,有一系列常数值可供选择,可同时选择多个,用按位或(|)连接起来,所以这些常数的宏定义都以O_开头,表示 or。

    • 必选项:以下三个常数中必须指定一个,且仅允许指定一个。

      • O_RDONLY:只读打开
      • O_WRONLY:只写打开
      • O_RDWR:可读可写打开
    • 常用可选项:可以同时指定0个或多个,和必选项按位或起来使用。

      • O_APPEND:追加,如果文件已有内容,这次打开文件所写的数据附加到文
        件的末尾而不覆盖原来的内容。

      • O_CREAT:若此文件不存在则创建它。使用此选项时需要提供第三个参数mode,表示该文件的访问权限。注:文件最终权限:mode & ~umask.

        int fd=open("./a.txt",O_RDONLY | O_CREAT,0666);
        //文件掩码为0002,其他人不会有写权限,0664
        
      • O_ExCL:如果同时指定了O_CREAT,并且文件已存在,则出错返回。

      • O_TRUNC:如果文件已存在,将其长度截断为为0字节。

      • O_NONBLOCK:设置非阻塞模式

        • 普通文件默认是非阻塞的,内核缓冲区保证了普通文件I/O不会阻塞,
          打开普通文件一般会忽略该参数
        • 设备、管道和套接字默认是阻塞的,以O_NONBLOCK方式打开可以做
          非阻塞IO (Nonblockl/O)

函数返回值:

  • 成功:返回一个最小且未被占用的文件描述符
  • 失败:返回-1,并设置errno值
关闭文件

int close(int fd);

image-20230727105606881

文件的写入与读取

读文件

read函数:

从打开的设备或文件中读取数据

函数原型:

ssize_t read(int fd, void *buf, size_t count);

函数参数:

  • fd:文件描述符
  • buf:读取的数据保存在缓冲区 buf中
  • count: buf 缓冲区存放的最大字节数

函数返回值:

  • >0:读取到的字节数

  • =0:文件为空/文件读取完毕

  • =-1:出错,并设置errno

image-20230728095029107

写文件

函数描述:
向打开的设备或文件中写数据函数原型:
ssize_t write(int fd, const void *buf, size_t count);

函数参数:

  • fd:文件描述符
  • buf:缓冲区,要写入文件或设备的数据count: buf中数据的长度

函数返回值:

  • 成功:返回写入的字节数
  • 错误:返回-1并设置errno
偏移量

所有打开的文件都有一个当前文件偏移量(current file offset),也叫读写偏移量和指针。文件偏移量是文件描述符的属性。文件偏移量通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数(下一个read()或write()操作的文件起始位置)。文件的第一个字节的偏移量为0。文件打开时,会将文件偏移量设置为指向文件开始(使用O_APPEND除外),以后每次read()和write()会自动对其调整,以指向已读或已写数据的下一字节。因此连续的read()和write()将按顺序递进,对文件进行操作。
在不显示地修改文件偏移量的前提下:

  • 对同一文件进行读写会产生追加效果,原因为在读取一段数据后,文件偏移量到读取数据后的下一位置,这时对此文件进行写操作,不会覆盖文件前面的内容。
  • 而对不同文件进行读写会产生覆盖效果,虽然在读取文件一段数据后,文件偏移量到读取数据后的下一位置,但在另一文件中,偏移量仍在文件的开头(offset=0),将一文件读取到的数据从另一文件的开头开始写入,自然而然会进行覆盖。
对同一文件读写产生追加效果

image-20230728101635002

对不同文件读写产生覆盖效果

image-20230728100833191

对不同文件写入,追加

打开文件时访问模式添加O_APPEND

image-20230728184119604 image-20230728184114384
对同一个文件进行覆盖

读取文件内容后,文件偏移量不在开头位置,要进行覆盖,需要设置文件描述符的偏移量为0,使用lseek()函数。

image-20230728105530737

偏移量的操作

使用lseek 函数可以改变文件的偏移量。

函数描述:移动文件指针头文件
#include <sys/types.h>

#include <unistd.h>
函数原型:
off_t lseek(int fd, off_t offset, int whence);

函数参数:

  • fd:文件描述符
  • offset:字节数,以whence参数为基点解释offset
  • whence:解释offset参数的基点
    • SEEK_SET:文件偏移量设置为offset
    • SEEK_CUR:文件偏移量设置为当前文件偏移量加上offset,offset可以为负数
    • SEEK_END:文件偏移量设置为文件长度加上offset,offset可以为负数

函数返回值:

  • 若lseek成功执行,则返回新的偏移量
  • 失败返回-1,并设置error
lseek()常用操作
  • 文件指针移动到头部
lseek(fd,0,SEEK_SET);
  • 获取文件指针当前位置
lseek(fd,0,SEEK_CUR);
  • 获取文件长度
lseek(fd,0,SEEK_END);
  • 实现文件扩展

    扩展后需要在扩展区执行一次写操作才能扩展成功

    • 使用SEEK_SET

      使用SEEK_SET扩展时,设置的字节数大小要比当前文件长度大,才会扩展

请添加图片描述

  • 使用SEEK_END
lseek(fd,100,SEEK_END);
练习

实现cp指令的功能

cp ./a.txt …/b.txt

int main(int argc, char* argv[])
{
   
        if(argc!=3){
   
            printf("输入正确的参数!");
            return 0;
        }
        char* path1=argv[1];
        char* path2=argv[2];
        int fd1=open(path1,O_RDWR);
        int fd2=open(path2,O_RDWR|O_CREAT|O_TRUNC,0666);//若文件存在,长度截断为0
        int read_count=-1;
        char buff[64];
        while(read_count!=0){
   
                read_count=read(fd1,buff,sizeof(buff));
               	write(fd2,buff,read_count);
        }
        close(fd1);<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值