首页 > 其他分享 >文件IO

文件IO

时间:2023-08-18 10:22:38浏览次数:17  
标签:返回 文件 int char IO 返回值 include

目录


1.系统IO

在裸机开发中,我们的程序直接与硬件打交道,应用直接操作硬件,必须了解硬件的具体实现细节,无并发,不能同时运行多个程序

app <----> hardware

在Linux开发中,程序和OS打交道,开发人员只需要将重心放在业务的实现逻辑上,而不需要考虑硬件的具体实现细节,提供并发,可以同时运行多个程序,占用资源较大

app <----> OS <---->hardware

操纵系统(OS):管理和分配硬件资源的系统软件,其向应用层提供进程管理,内存管理,文件管理,网络管理等服务,而文件IO就是使用文件系统所提供的IO接口进行应用开发,对于系统提供的文件操作的接口我们称之为系统IO

在系统IO中,操作系统给我们提供的接口包括 open read write close lseek 等。

1.1文件系统

文件系统:用来存储、组织、管理文件的一套方法、方式、协议以及软件实现等

文件包括 文件属性文件内容

文件属性:i-nodeinode ,文件存在与否的唯一表示,包括文件大小、文件类型、文件时间......

1.1.1文件的操作过程

硬件上:inode节点标识相应的文件

Linux内核:会为每一个inode生成一个struct inode 来描述一个文件的物理inode信息,一个struct inode只对应一个文件,多个struct inode可以指向同一个文件;当应用层打开一个文件的时候,OS 会为被打开的文件创建一个struct file 来描述这个被打开的文件;在struct file中 会保存 文件状态标记、文件偏移量、struct inode *;每打开一个文件,肯定会有一个struct file,一个文件可以被不同的进程打开;linux系统为了屏蔽文件操作的具体实现细节,它会为每一个进程创建一个进程文件表项,用来保存每个进程所打开的文件struct file*,应用层最终的到的用来描述文件的数据只是进程文件表项中的某一项(下标)

APP-> fd -> struct file*FD[] -> struct file -> struct inode -> inode ->文件内容

在应用层我们只需要关心如何得到这个文件描述符-fd,以及如何操作这个fd,操作系统会为我们提供一系列的接口去操作这个fd,这些接口我们称之为 系统IO

1.2Linux系统IO

1.2.1 open

//功能:打开/创建一个文件
//头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

//声明
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
/**
*pathname:路径名 带路径的文件名
*flags:打开方式
*	O_RDONLY 只读
*	O_WRONLY 只写
*	O_RDWR 读写
*	O_CREAT 创建,如果文件不存在就创建文件
*	O_APPEND 追加,文件打开后,光标/偏移量在文件尾
*	O_TRUNC 截断,打开时清空文件
*	O_EXCL 测试文件是否存在
*	O_NONBLOCK 非阻塞方式打开文件
*
*mode:指定文件创建时的权限,如果flags没有指定O_CREAT,这个参数就没有意义
*	S_IRWXU  00700 user用户可读可写可执行
*	S_IRUSR  00400 user用户可读
*	S_IWUSR  00200 user用户可写
*	S_IXUSR  00100 user用户可执行
*	S_IRWXG  00070 group用户可读可写可执行
*	S_IRGRP  00040 group用户可读
*	S_IWGRP  00020 group用户可写
*	S_IXGRP  00010 group用户可执行
*	S_IRWXO  00007 其他用户可读可写可执行
*	S_IROTH  00004 其他用户可读
*	S_IWOTH  00002 其他用户可写
*	S_IXOTH  00001 其他用户可执行
*
*返回值:
*	成功,返回一个文件描述符 >2
*	失败,返回-1,并且errno被设置
*/

  • 对于阻塞状态,如果一个文件没有内容,那么read会阻塞,直到这个空间有内容;如果这个文件没有空间了,那么write就会阻塞,直到这个文件有空间
  • 对于非阻塞状态,如果一个文件没有内容,那么read会直接返回一个错误;如果这个文件没有空间了,那么write就会直接返回一个错误
  • 操作系统会为每一个进程自动打开三个文件,标准输入文件STDIN_FILENO 0标准输出文件STDOUT_FILENO 1标准出错文件STDERR_FILENO 2
  • errno错误编号:不同的错误编号代表不同的错误原因,可以使用perror函数输出当前错误号所对应的错误原因

1.2.2 read

//功能:从一个文件中读取数据
//头文件
 #include <unistd.h>

//声明
ssize_t read(int fd, void *buf, size_t count);
/**
*fd:要读取的文件的文件描述符
*buf:保存数据的地址
*count:读取数据的字节数
*返回值:
*	成功:返回实际读取到的字节数
*	失败:返回-1,并设置errno
*/

1.2.3 write

//功能:向一个文件中写入数据
//头文件
#include <unistd.h>

//声明
ssize_t write(int fd, const void *buf, size_t count);
/**
*fd:要写入的文件的文件描述符
*buf:保存数据的地址
*count:写入数据的字节数
*返回值:
*	成功:返回实际写入到的字节数
*	失败:返回-1,并设置errno
*/

1.2.4 close

//功能:关闭一个文件
//头文件
#include <unistd.h>

//声明
int close(int fd);
/**
*fd:要关闭的文件的文件描述符
*返回值:
*	成功:返回0
*	失败:返回-1,并设置errno
*/

1.2.5 lseek

文件偏移量:标识文件读写的位置

read/write的过程中,当我们第一次打开文件时,文件偏移量默认在开头,当read/write10个字节后,文件偏移量会相应的移动10个字节。

//功能:重定位文件偏移量
//头文件
#include <sys/types.h>
#include <unistd.h>

//声明
off_t lseek(int fd, off_t offset, int whence);
/**
*fd:文件描述符
*offset:偏移量
*	为正表示向后偏移,为负表示向前偏移,单位是字节
*whence:偏移开始的位置
*	SEEK_SET 文件头
*	SEEK_CUR 当前
*	SEEK_END 文件尾
*返回值:
*	成功:返回距离文件头的偏移量
*	失败:返回-1,并设置errno
*/

1.2.6 umask

//功能:设置一个文件在创建时的掩码
//头文件
#include <sys/types.h>
#include <sys/stat.h>

//声明
mode_t umask(mode_t mask);
/**
*mask:指定文件掩码
*返回值:
*	返回原先的文件掩码
*/

1.2.7获取当前的工作目录

getcwd getwd get_current_dir_name

//头文件
#include <unistd.h>

//声明
char *getcwd(char *buf, size_t size);
/**
*buf:保存当前获取到的进程工作目录,以字符串形式
*size:buf空间的最大长度,如果当前工作目录的字符串长度大于size-1,函数就会报错
*返回值
*	成功:返回执行工作目录的指针
*	失败:返回NULL,并设置errno
*/
char *getwd(char *buf);
/**
*buf:保存当前获取到的进程工作目录,以字符串形式
*返回值
*	成功:返回执行工作目录的指针
*	失败:返回NULL,并设置errno
*/
char *get_current_dir_name(void);//内部使用了malloc分配的空间,要free
/**
*返回值
*	成功:返回执行工作目录的指针
*	失败:返回NULL,并设置errno
*使用该函数前,需要定义一个宏 _GNU_SOURCE
*/

1.2.8改变进程当前的工作目录

chdir fchdir

//头文件
#include <unistd.h>

//声明
int chdir(const char *path);
/**
*path:要指定的工作路径
*返回值:
*	成功:返回0
*	失败:返回-1,并设置errno
*/
int fchdir(int fd);
/**
*fd:要指定的工作目录的文件描述符
*返回值:
*	成功:返回0
*	失败:返回-1,并设置errno
*/

1.2.9文件截短

truncate ftruncate

//功能:截短一个文件到固定的长度
//头文件
#include <unistd.h>
#include <sys/types.h>

//声明
int truncate(const char *path, off_t length);
/**
*path:文件路径
*length:截短长度
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/
int ftruncate(int fd, off_t length);
/**
*path:文件描述符
*length:截短长度
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/
  • 如果文件的大小大于lenth,截短
  • 如果文件的大小小于lenth,文件大小会变大为lenth

1.2.10删除文件

unlink 删除一个文件

rmdir 删除一个目录

//头文件
#include <unistd.h>

//声明
int unlink(const char *pathname);
/**
*pathname:文件路径
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/
int rmdir(const char *pathname);
/**
*pathname:文件路径
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/
  • unlink 调用时如果有进程打开了这个文件,并不会直接删除 inode,而是做一个删除标记,这个inode将会在使用完毕后删除

remove 删除一个文件/空目录

//头文件
#include <stdio.h>

//声明
int remove(const char *pathname);
/**
*pathname:文件路径
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/

1.2.11 文件属性

stat fstat lstat

//头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

//声明
int stat(const char *pathname, struct stat *statbuf);
/**
*pathname:文件路径
*statbuf:保存获得的文件属性
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/
int fstat(int fd, struct stat *statbuf);
/**
*fd:文件描述符
*statbuf:保存获得的文件属性
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/
int lstat(const char *pathname, struct stat *statbuf);
/**
*pathname:文件路径
*statbuf:保存获得的文件属性
*返回值:
*	成功返回0
*	失败返回-1,并设置errno
*/
  • 如果pathname对应的是一个符号链接,lstat获取的文件是符号链接本身,而stat获取的是符号链接所指向的文件

  • struct stat

    struct stat {
        dev_t     st_dev;         //设备号
        ino_t     st_ino;         //节点号
        mode_t    st_mode;        //文件类型和权限
        nlink_t   st_nlink;       //文件的硬链接数,不能跨文件系统
        uid_t     st_uid;         //用户ID
        gid_t     st_gid;         //组用户ID
        dev_t     st_rdev;        //设备号
        off_t     st_size;        //文件大小
        blksize_t st_blksize;     //块大小
        blkcnt_t  st_blocks;      //文件所占块数
    
        struct timespec st_atim;  //最后一次访问该文件的时间
        struct timespec st_mtim;  //最后一次修改该文件内容的时间
        struct timespec st_ctim;  //最后一次修改该文件属性的时间
    
    #define st_atime st_atim.tv_sec      /* Backward compatibility */
    #define st_mtime st_mtim.tv_sec
    #define st_ctime st_ctim.tv_sec
    };
    
  • 判断文件的类型

    S_ISREG(*.st_mode);			//为真,表示是一个普通文件 -
    S_ISDIR(*.st_mode);			//为真,表示是一个目录 d
    S_ISCHR(*.st_mode);			//为真,表示是一个字符设备 c
    S_ISBLK(*.st_mode);			//为真,表示是一个块文件 b
    S_ISFIFO(*.st_mode);		//为真,表示是一个管道文件 p
    S_ISLNK(*.st_mode);			//为真,表示是一个符号链接文件 l
    S_ISSOCK(*.st_mode);		//为真,表示是一个套接字文件 s
    
  • 判断文件的权限

    *.st_mode & S_IRUSR    	//为真,说明owner 用户具备可读的权限
    *.st_mode & S_IWUSR    	//为真,说明owner 用户具备可读的权限
        ......
    

1.3目录

目录和文件一样,都有inode ,在创建一个目录的时候,系统会为它预留一块空间——目录项数组空间,往其中添加一个文件,就会往目录项数组中新增一个目录项。

1.3.1目录操作

opendir 打开一个目录

//头文件
#include <sys/types.h>
#include <dirent.h>

//声明
DIR *opendir(const char *name);
/**
*name:都路径的目录名
*返回值:
*	成功,返回一个目录指针
*	失败,返回NULL,并设置errno
*/

readdir

//头文件
#include <dirent.h>

//声明
struct dirent *readdir(DIR *dirp);
/**
*dirp:目录指针
*返回值:
*	成功,返回一个目录项指针
*	失败,返回NULL,并设置errno
*/
  • struct dirent

    struct dirent {
        ino_t          d_ino;       /* Inode number */
        off_t          d_off;       /* Not an offset; see below */
        unsigned short d_reclen;    /* Length of this record */
        unsigned char  d_type;      /* Type of file; not supported
                                      by all filesystem types */
        char           d_name[256]; /* Null-terminated filename*/
    };
    

closedir

//头文件
#include <sys/types.h>
#include <dirent.h>

//声明
int closedir(DIR *dirp);
/**
*dirp:目录指针
*返回值:
*	成功,返回0
*	失败,返回-1,并设置errno
*/

2.标准IO

每个操作系统都提供了一套基于自身操作系统的IO接口---系统IO,每个操作系统对文件的管理和接口都是不一样的。

C标准委员会,制定了一套统一的文件接口---C标准IO库,主要统一对文件常用的接口的操作。

C标准IO库可以操作的文件:普通文本文件以及二进制文件

文本文件:无组织、无格式的文件,以字符的编码来解析,如.txt .c .h .s ......

二进制文件:有特定格式的文件,如.jpg .gif .mp3 ......

在标准IO库,用 FILE 结构体来描述或者表示一个文件的,这个结构体内部有两个缓冲区,一个读缓冲,一个是写缓冲。

同步问题:缓冲区的数据什么时候同步到外设上

缓冲区有三种类型:

行缓冲:缓冲区的数据达到一行(如果数据中有换行符也表示一行结束),同步到外设中

全缓冲:缓冲区的数据要填满整个缓冲区,才同步到外设中去

无缓冲:缓冲区中有一个字节,就同步到外设上

标准IO库,会自动为每个进程,打开三个标准IO流:标准输入流 : FILE * stdin,标准输出流 : FILE * stdout,标准出错流 : FILE * stderr

2.1标准IO的函数接口

2.1.1打开和关闭

fopen fclose

//头文件
#include <stdio.h>

//声明
FILE *fopen(const char *pathname, const char *mode);
/**
*pathname:要打开的文件
*mode:打开文件的方式
*	"r" 只读打开,文件不存在报错,打开后光标在开头
*	"r+" 读写打开,文件不存在报错,打开后光标在开头
*	"w" 只写打开,文件不存在则创建,打开后文件内容截短/清空
*	"w+" 读写打开,文件不存在则创建,打开后文件内容截短/清空
*	"a" 追加打开,文件不存在则创建,打开后光标在末尾,文件不会被截短
*	"a+" 读写打开,文件不存在则创建,原始读的位置在开头,原始写的位置在结尾
*返回值:
*	成功,返回一个文件指针
*	失败,返回NULL,并设置errno
*/

int fclose(FILE *stream);
/**
*stream:要关闭的文件
*返回值:
*	成功,返回0
*	失败返回-1,并设置errno
*/

2.1.2读写流

每次读写一个字符

//头文件
#include <stdio.h>

//声明
int fgetc(FILE *stream);

int getc(FILE *stream);

int getchar(void);

int fputc(int c, FILE *stream);

int putc(int c, FILE *stream);

int putchar(int c);

每次读写一行

//头文件
#include <stdio.h>

//声明
char *gets(char *s);

char *fgets(char *s, int size, FILE *stream);

int puts(const char *s);

int fputs(const char *s, FILE *stream);

直接读写

fread fwrite

//头文件
#include <stdio.h>

//声明
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
/**
*ptr:指向用来存储的空间
*size:每个元素所占的字节数
*nmemb:要读取的元素的个数
*stream:要读取的文件
*返回值:
*	成功,返回实际读取到的元素的个数
*	失败,返回-1,并设置errno
*/
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
/**
*ptr:指向用来存储的空间
*size:每个元素所占的字节数
*nmemb:要写入的元素的个数
*stream:要写入的文件
*返回值:
*	成功,返回实际写入的元素的个数
*	失败,返回-1,并设置errno
*/

2.1.3冲洗流

fflush 同步

//头文件
#include <stdio.h>

//声明
int fflush(FILE *stream);
/**
*stream:要冲洗的流文件
*返回值:
*	成功,返回0     
*	失败,返回-1,并设置errno
*对于输出流,该函数将写缓冲的数据,更新到外设中
*对于输入流,该函数将都缓冲的数据,直接丢弃
*对于NULL,该函数将进程打开的所有输出文件流进行同步
*/

2.1.4定位流

fseek ftell rewind

//头文件
#include <stdio.h>

//声明
int fseek(FILE *stream, long offset, int whence);
/**
*stream:要重新定位的流文件
*offset:偏移量,左负右正
*whence:偏移起始位置
*	SEEK_SET
*	SEEK_CUR
*	SEEK_END
*返回值:
*	成功,返回0
*	失败,返回-1,并设置errno
*/
long ftell(FILE *stream);
/**
*stream:指向流文件
*返回值:
*	成功,返回光标距离文件头的字节数
*	失败,返回-1,并设置errno
*/
void rewind(FILE *stream);//将光标定位到文件头

2.1.5文件出错/结束标志

EOF 文件结束标志

//头文件
#include <stdio.h>
//声明
int feof(FILE *stream);
/**
*stream:指向流文件
*返回值:
*	文件到达末尾,返回非0
*	文件没有到达末尾,返回0
*/

2.1.6格式化IO

格式化输入 scanf sscanf fscanf

//头文件
#include <stdio.h>
//声明
int scanf(const char *format, ...);
/**
*format:格式化字符串,指定用户输入的格式
*...:地址列表
*返回值:成功匹配的变量个数
*/
int fscanf(FILE *stream, const char *format, ...);
/**
*stream:输入文件流
*format:格式化字符串,指定用户输入的格式
*...:地址列表
*返回值:成功匹配的变量个数
*/
int sscanf(const char *str, const char *format, ...);
/**
*str:从str指定的字符串中输入
*format:格式化字符串,指定用户输入的格式
*...:地址列表
*返回值:成功匹配的变量个数
*/

格式化输出 printf sprintf fprintf

//头文件
#include <stdio.h>
//声明
int printf(const char *format, ...);
/**
*format:格式化字符串
*...:对象列表
*返回值:实际打印的字符个数
*/
int fprintf(FILE *stream, const char *format, ...);
/**
*stream:输出文件流
*format:格式化字符串
*...:对象列表
*返回值:实际打印的字符个数
*/
int sprintf(char *str, const char *format, ...);
/**
*str:输出到str指定的空间
*format:格式化字符串
*...:对象列表
*返回值:实际打印的字符个数
*/
int snprintf(char *str, size_t size, const char *format, ...);
/**
*str:输出到str指定的空间
*size:指定长度
*format:格式化字符串
*...:对象列表
*返回值:实际打印的字符个数
*/

标签:返回,文件,int,char,IO,返回值,include
From: https://www.cnblogs.com/aalynsah/p/17639710.html

相关文章

  • linux 文件压缩常用命令
    一、常见文件压缩格式Windows和Linux下的压缩文件格式有一些共同的,也有一些不同的。以下是一些常见的压缩文件格式:.zip:这是Windows中最常用的压缩格式,也是Linux中可以识别的一种压缩格式,可以方便地和Windows系统通用压缩文件。在Linux中,可以使用zip和unzip命令来压缩和解压.zip文......
  • docker容器daemon.json配置文件解析
    docker版本高于1.12,配置文件的默认径为:/etc/docker/daemon.json{“api-cors-header”:"",在引擎API中设置CORS标头“authorization-plugins”:[],要加载的授权插件“bridge”:"",将容器附加到网桥“cgroup-parent”:"",为所有容器设置父cgroup“cluster-store......
  • OpenCV3.3深度神经网络DNN模块 实例1:读取单张PNG文件(opencv3.3环境测试)
    1#include<opencv2/opencv.hpp>2#include<opencv2/dnn.hpp>//dnn模块类3#include<iostream>45usingnamespacecv;6usingnamespacestd;78intmain(intargc,char**argv){9Matsrc=imread("tx.png");10......
  • 如何让WPF中的ValidationRule实现参数绑定
    背景应用开发过程中,常常会对用户输入内容进行验证,通常是基于类型、范围、格式或者特定的要求进行验证,以确保输入符合预期。例如邮箱输入框校验输入内容是否符合邮箱格式。在WPF中,数据模型允许将ValidationRules与Binding对象关联,可以通过继承ValidationRule类并重写Validate方法......
  • GitHub: remote:Support for password authentication was removed on August 13,2021
    使用gitpushoriginmaster向远程仓库推送时被告知:remote:SupportforpasswordauthenticationwasremovedonAugust13,2021.Pleaseuseapersonalaccesstokeninstead.ush的时候需要输入github的账户名和密码,而这里的大概意思就是密码验证在2021年8月13号被移除了,需要......
  • Clion 2023.1.3最新版安装使用教程,附激活码!
    Clion是一款专门开发C以及C++所设计的跨平台的IDE。它是以inteliJ为基础设计的,包含了许多智能功能来提高开发人员的生产力。这种强大的IDE帮助开发人员在Linux、OSX和Windows上来开发C/C++,同时它还能使用智能编辑器来提高代码质量、自动代码重构并且深度整合Cmake编译系统,从而提......
  • java 每天23点定时删除某个Folder下的文件
    importjava.io.IOException;importjava.nio.file.*;importjava.time.LocalDate;importjava.time.LocalDateTime;importjava.time.LocalTime;importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concu......
  • SP8591 PRIMPERM - Prime Permutations 题解
    题目链接题目大意给出\(1\)个数\(n\),求\(n\)的各位拆分后重新排列组合得到新数是质数的个数。思路(欧拉筛,全排列)对于求质数,与其每组数据运行\(1\)次质数筛,不如在一开始就筛出\([1,10^7]\)内的所有质数,用bool数组统计起来,这样只需运行\(1\)次质数筛,大大节约了时间......
  • CH32V003在MRS中的头文件定义
    在MRS的头文件core_riscv.h中有如下的定义。 #define__Ivolatileconst#define__Ovolatile#define__IOvolatile 上述定义,通过define语句把__IO等效为volatile,把__O等效为volatile,把__I等效为volatileconst。一般来说宏定义都用大写形式,但因......