IO进程线程(三)文件IO之open/close read/write lseek

一、文件IO

(一)概念

文件IO就是系统调用,用户空间进入内核空间的过程就是系统调用。
与标准IO相比,系统调用没有缓冲机制,效率较低,可移植性也相对较差,但是实时性高。

文件描述符 是使用open函数打开文件时的返回值,一般叫做fd,这个fd就代表这个打开的文件,以后对文件的读写操作,就是通过这个文件描述符fd来完成的。

fd是一个整数,一般默认情况下,一个程序中文件描述符的范围0-1023共计1024个,
使用ulimit -a可以查看一个程序中可以打开的文件的个数限制
在这里插入图片描述
(open files 后面对应的就是 这个值也可以使用命令ulimit -n 2048来修改 但一般都是用默认值)

在一个程序启动的过程中,默认就会打开三个描述符(0 1 2)。
如果再打开新文件,一般是从3开始的。

文件描述符功能
0标准输入
1标准输出
2标准出错

(二)open和close 函数的使用

1. open

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
功能:
    使用文件IO的方式打开一个文件
参数:
    pathname:文件的路径和名字
    flags:
        O_RDONLY  只读的方式打开文件
        O_WRONLY   只写的方式打开文件
        O_RDWR    读写的方式打开文件
        ----上面三个必须三选一  下面的是附加选项----
        O_APPEND  以追加的方式打开文件
        O_CREAT  如果文件不存在,则新建这个文件
            如果指定了这个宏,则第三个参数 mode 必须填
            mode代表的是创建文件的权限
            创建普通文件的最大权限为 0666
            也就是说我们给mode赋值 最大应该就为 0666
            但是实际上创建文件的权限还得涉及 掩码 umask
            umask的值 默认为 0002  这个值也可以改的
            最终的权限 = (mode & ~umask)
            所以 即使给的是 0666 最终的权限也是 0664
        O_EXCL 需要和 O_CREAT 一起使用 如果文件不存在会创建文件
                如果文件存在,会报错 错误码:EEXIST
        O_TRUNC :如果文件存在就清空
    mode:代表文件的权限 一般用8进制表示
    	mode_tunsigned int
返回值:
    成功  文件描述符(返回的文件描述符遵循未被打开的最小原则)
    失败  -1 重置错误码
(2)flags操作的原理
标准io文件io说明
rO_RDONLY以只读的方式打开文件
r+O_RDWR以读写的方式打开文件
wO_WRONLY|O_CREAT|O_TRUNC, 0666以只写的方式打开文件,文件存在就清空不存在就新建
w+O_RDWR|O_CREAT|O_TRUNC, 0666以读写的方式打开文件,文件存在就清空不存在就新建
aO_WRONLY|O_APPEND|O_CREAT,0666以结尾写的方式打开文件,不存在就新建
a+O_RDWR|O_APPEND|O_CREAT,0666以读和结尾写的方式打开文件,不存在就新建

2. close 函数的使用

#include <unistd.h>
int close(int fd);
功能:关闭文件
参数:fd:文件描述符
返回值:
    成功 0
    失败 -1 重置错误码
函数openclose
头文件sys/types.h、sys/stat.h、fcntl.hunistd.h
参数char *pathname, int flags, mode_t modeint fd
返回值int 成功返回文件描述符;失败返回-1,重置错误码int 成功返回0,失败返回-1,重置错误码
功能打开文件关闭文件
备注返回的文件描述符遵循未被打开的最小原则

(三)read/write函数

1. read

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:
    从文件fd中读取最多count个字节到buf中
参数:
    fd:文件描述符
    buf:用来存放读到的内容的缓冲区的首地址
    count:想要读取的字节数
    	ssize_tsize_tlong
返回值:
    成功  实际读到的字节数(读到文件结束会返回0)
    失败  -1  重置错误码

2. write

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:
    把buf指向的内容写最多count个到文件fd中
参数:
    fd:文件描述符
    buf:要写入的内容的首地址
    count:想要写入的字节数
返回值:
    成功  实际写入的字节数
    失败  -1  重置错误码
函数readwrite
头文件unistd.hunistd.h
参数int fd, void *buf, size_t countint fd, void *buf, size_t count
返回值ssize_t 实际读取的字节数,读到结尾返回0;失败返回-1,重置错误码ssize_t 实际写入的字节数,失败返回-1,重置错误码
功能从文件fd中读取最多count个字节到buf指向的内存中将buf中最多count个字节写入到文件fd中

3. 使用示例

功能需求:使用write和read复制文件,要求从命令行传参

需求分析
read函数会返回实际读取的字节数。

代码实现

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

int main(int argc, char const *argv[])
{
    if(3 != argc){
        printf("Usage:./a.out src dest\n");
        exit(-1);
    }
    int src_fd = open(argv[1],O_RDONLY);
    int dest_fd = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);
    
    char buff[10]={0};
    int nbyte=0;
    while(0 < (nbyte=read(src_fd,buff,sizeof(buff)))){
        if(nbyte != write(dest_fd,buff,nbyte))
            perror("write error");
    }
    return 0;
}

(四)光标操作

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:
    设置光标位置
参数:
    fd:文件描述符
    offset:偏移量
        0  不偏移
        >0  向后偏移
        <0  向前偏移
        off_tlong
    whence:相对位置
        SEEK_SET  相对于文件开头
        SEEK_CUR  相对于当前位置
        SEEK_END  相对于文件结尾
返回值:
    成功  光标新位置距离文件开头的偏移量
    失败  -1  重置错误码

使用实例:
    lseek(fd, 0, SEEK_SET);//将光标定位到文件开头
    lseek(fd, 0, SEEK_END);//将光标定位到文件结尾
    lseek(fd, 10, SEEK_CUR);//将光标向后偏移10个字节
    lseek(fd, -10, SEEK_CUR);//将光标向前偏移10个字节
    lseek(fd, 10, SEEK_SET);//将光标定位到文件开头第10个字节
    lseek(fd, -10, SEEK_END);//将光标定位到文件倒数第10个字节

二、文件IO和标准IO的区别

(一)open和fopen

文件IO标准IO
函数openfopen
功能以文件IO的方式打开文件以标准IO的方式打开文件
参数char *pathname,int flags,mode_t modechar *pathname,char *mode
返回值int 成功返回fd(遵循未被打开的最小原则),失败返回-1,重置错误码FILE* 成功返回文件指针;失败返回NULL,重置错误码

(二)close和fclose

文件IO标准IO
函数closefclose
功能关闭文件关闭文件
参数int fdFILE *fp
返回值成功,0;失败,-1,重置错误码成功,0;失败,EOF,重置错误码

(三)read和fread

文件IO标准IO
函数readfread
头文件unistd.hstdio.h
功能从文件fd中读取最多count个字节到buf指向的内存中在文件stream中读取nmemb个size大小的项目到ptr指向的内存中
参数int fd, void *buf, size_t countvoid *ptr, size_t size, size_t nmemb, FILE *stream
返回值ssize_t 实际读取的字节数,读到结尾返回0;size_t 成功,实际读到的项目数;失败,小于项目数的数(或者0)
  • 注:
  • fread中,关于size参数,是因为ptr类型为void*,因此由size来控制单个项目的字节数
  • fread不会区分文件尾还是出错,因此需要再进一步使用feof和ferror两个函数来判断是到达了文件尾还是出错了。

补充:标准IO中fgets和fread比较

fgetsfread
功能从文件stream中读取最多 size-1 个字节到s指向的缓冲区中,遇到EOF或者’\n’会停止读取(‘\n’也会被读到buff中 且在结尾加一个’\0’)在文件stream中读取nmemb个size大小的项目到ptr指向的内存中
参数char *s, int size, FILE *streamvoid *ptr, size_t size, size_t nmemb, FILE *stream
返回值char* 成功,s的首地址;文件结束或者出错,NULLsize_t 成功,实际读到的项目数;失败,小于项目数的数(或者0)

(四)write和fwrite

文件IO标准IO
函数writefwrite
头文件unistd.hstdio.h
参数int fd, void *buf, size_t countvoid *ptr, size_t size, size_t nmemb, FILE *stream
返回值ssize_t 实际写入的字节数,失败返回-1,重置错误码size_t 成功,实际写入到的项目数;失败,小于项目数的数(或者0)
功能将buf中最多count个字节写入到文件fd中把ptr指向的空间中的内容写入nmemb个size大小到文件stream中

补充:标准IO中fputs和fwrite比较

fputsfwrite
功能将字符串s写入文件stream中把ptr指向的空间中的内容写入nmemb个size大小到文件stream中
参数char *s,FILE * streamconst void *ptr, size_t size, size_t nmemb, FILE *stream
返回值成功,非负数;失败,EOF(-1)成功 实际写入到的项目数;失败 小于项目数的数(或者0)

(五)fseek和lseek

文件IO标准IO
函数lseekfseek
头文件sys/types.h、unistd.hstdio.h
参数int fd, off_t offset, int whenceFILE *stream, long offset, int whence
返回值成功时返回新位置距离文件开头的偏移量,失败返回-1,重置错误码成功返回0;失败返回-1,重置错误码
  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值