Linux:基础IO——复习C语言文件IO相关操作

1.C语言操作文件接口

(1) fopen函数

函数原型:
FILE *fopen(const char *path,const char *mode);
参数解释:
path:待打开的文件(文件路径 + 文件名称)
mode:以何种方式打开
返回值:打开文件成功返回文件流指针,打开失败返回NULL

打开方式:

打开方式 解释
r 以只读方式打开,当文件不存在的时候,就会打开失败
r+ 以读写方式打开,当文件不存在的时候,就会打开失败
w 以只写方式打开。如果文件不存在,则会创建文件,如果文件存在则会截断(清空)文件
w+ 以读写方式打开文件,如果文件不存在,则创建文件;如果文件存在,则会截断(清空)文件
a 以追加方式打开,仅支持写,如果文件不存在,则会创建文件;当前的文件流指针指向了文件的末尾
a+ 以追加方式打开,支持读写,如果文件不存在,则创建文件,当前文件流指针指向了文件的末尾

(2)fwrite函数

函数原型:
size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);
参数解释:
ptr:要往文件中写的内容
size: 写入块的大小,单位是字节
nmemb:块的个数,单位是个
stream:文件流指针
返回值:返回写入成功时块的个数(不是写入成功字节的数量)

注意:一般在程序中使用的时候,是将size设置成1,则nmembj就表示写入的字节数量

(3) fread函数

函数原型:
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
参数解释:
ptr:要将读到的内容保存到哪里
size: 每次读块的大小
nmemb: 块的个数
stream:文件流指针
返回值:成功读到的块的个数

(4)fseek函数

函数原型:
int fseek(FILE *stream, long offset,int whence);
stream:文件流指针
offset:偏移量
whence:
	SEEK_SET:文件流指针偏移到文件头部
	SEEK_CUR:文件流指针偏移到当前位置
	SEEK_END:文件流指针指向文件末尾位置

(5)fclose函数

函数原型:
int fclose(FILE *fp);
作用:关闭文件流指针

代码:

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

int main()
{
    
    
    FILE* fp = fopen("./linux", "r+");
    if(!fp)
    {
    
    
        perror("fopen");
        return -1;
    }


    char buf[1024] = {
    
    0};
    strcpy(buf, "linux-57");
    ssize_t w_ret = fwrite(buf, 1, 9, fp);
    printf("w_ret:%d\n", w_ret);
    
    fseek(fp, 0, SEEK_SET);

    memset(buf, '\0', sizeof(buf));
    ssize_t r_ret  = fread(buf, 1, sizeof(buf) - 1, fp);
    printf("r_ret:%d, ---  %s\n", r_ret, buf);

    printf("open success\n");
    return 0;
}

以上这些函数都是库函数,时C库中提供给程序员调用的函数,接下来再给大家分享一下操纵系统内核为程序员提供的函数。

2.系统调用函数的操作文件接口

(1)open函数

函数原型:
int open(const char *pathname, int flags, mod_t mode);
参数解释:
pathname:要打开的文件名称(路径+名称)
flags: 以何种方式打开
mode: 权限
返回值:打开成功,返回大于等于0的数字,是文件描述符,打开失败返回-1

flags处传递的参数为宏定义,分为必须的宏和可选的宏两种:
必须的宏:

名称 解释
O_RDONLY 只读方式
O_WRONLY 只写方式
O_RDWR 读写方式

可选的宏:

名称 解释
O_APPEND 追加
O_TRUNC 截断
O_CREAT 文件不存在则创建

使用的时候,用必须的宏和可选的宏组合使用,必须的宏和可选的宏之间使用按位或的方式。
例如:

O_RDWR | O_CREAT

(2)read函数

函数原型:
ssize_t read(int fd,  void *buf,size_t count);
参数解释:
fd:文件描述符,open的返回值
buf:要将读到的内容放到那里去
count: 最大可以读多少个,单位字节
返回值: 返回读到的字节数量

(3)write函数

函数原型:
ssize_t read(int fd,  const void *buf,size_t count);
参数解释:
fd:文件描述符,open的返回值
buf:往文件中写的内容
count: 写的内容的大小
返回值: 写成功的字节数量

(4)lseek函数

函数原型:
off_t lseek(int fd,  off_t offset,int whence);
参数解释:
fd:文件描述符,open的返回值
offset:偏移量
whence: 
	SEEK_SET
	SEEK_CUR
	SEEK_END

(5)close

函数原型:
int close(int fd);
作用:关闭文件描述符

代码:

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


int main()
{
    
    

    close(0);
    int fd = open("./linux", O_RDWR | O_CREAT, 0664);
    if(fd < 0)
    {
    
    
        perror("open");
        return -1;
    }
    printf("%d\n", O_RDWR | O_CREAT);
    printf("fd : %d\n", fd);

    while(1)
    {
    
    
        sleep(1);
    }

    return 0;
}

文件描述符

概念:文件描述符其实就是从0开始的小整数,当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。而open执行系统调用,所以必须将进程和文件关联起来。每个进程都有一个指针*files,指向一张表files_struct,该表最重要的部分就是包含一个指指针数组,每个元素都是一个指向打开文件的指针。所以,本质上,文件描述符就是该数组的下标,所以,只要拿着文件描述符,就可以找到对应的文件。
在这里插入图片描述

文件描述符的分配规则

首先我们来看下面的代码的结果

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    
    
 int fd = open("myfile", O_RDONLY);
 if(fd < 0){
    
    
 perror("open");
 return 1;
 }
 printf("fd: %d\n", fd);
 close(fd);
 return 0;
}

运行结果:
在这里插入图片描述
结果为fd:3

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    
    
 close(0);
 //close(2);
 int fd = open("myfile", O_RDONLY);
 if(fd < 0){
    
    
 perror("open");
 return 1;
 }
 printf("fd: %d\n", fd);
 close(fd);
 return 0;
}

运行结果:
在这里插入图片描述
关闭2或者0,发现结果为fd:0
可以得出,文件描述符的分配规则为:在file_struct数组中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

3.重定向

如果我们把1关闭了,就会看到这样的现象

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
    
    
 close(1);
 int fd = open("myfile", O_WRONLY|O_CREAT, 00644);
 if(fd < 0){
    
    
 perror("open");
 return 1;
 }
 printf("fd: %d\n", fd);
 fflush(stdout);
 
 close(fd);
 exit(0);
}

运行结果:
在这里插入图片描述
此时,我们发现,本来应该输出到显示器上的内容,输出到了文件 myfile 当中,其中,fd=1。这种现象叫做输出重定向。常见的重定向有:>, >>, <
重定向本质:在这里插入图片描述
##dup2函数

函数原型:
#include <unistd.h>
int dup(int oldfd, int newfd);

例子:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
    
    
 int fd = open("./log", O_CREAT | O_RDWR);
 if (fd < 0) {
    
    
 perror("open");
 return 1;
 }
 close(1);
 dup2(fd, 1);
 for (;;) {
    
    
 char buf[1024] = {
    
    0};
 ssize_t read_size = read(0, buf, sizeof(buf) - 1);
 if (read_size < 0) {
    
    
 perror("read");
 break;
 }
 printf("%s", buf);
 fflush(stdout);
 }
 return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43825377/article/details/113921256