04.文件I/O基础

        一个通用的 IO 模型通常包括打开文件、读写文件、关闭文件这些基本操作, 主要涉及到 4 个函数: open()、 read()、 write()以及 close()。下面是一个具体的读写应用的例子:

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

int main(int argc,char *argv[])
{
    char buffer[1024];  //定义缓冲区
    int fd1,fd2;    //用于保存文件描述符
    int ret;

    /*打开src_file文件*/
    fd1 = open("./src_file",O_RDONLY);  //以只读的方式打开当前目录下的src_file文件
    if(fd1 == -1){  //文件描述符为-1,表示打开失败
        printf("Open file:src_file Failed!\r\n");
        return -1;
    }

    /*新建test_file文件并打开*/
    fd2 = open("./test_file",O_WRONLY | O_CREAT | O_EXCL,S_IRWXU | S_IRGRP | S_IROTH);
    //O_WRONLY以读写的方式打开
    //O_CREAT如果文件不存在则创建该文件
    //O_EXCL 如果文件已存在则返回错误
    //S_IRWXU 允许文件所属者读、写、执行文件
    //S_IRGRP 允许同组用户读文件
    //S_IROTH 允许其他用户读文件
    if(fd2 == -1){ 
        printf("Open file:test_file Failed!\r\n");
        ret = -1;
        goto err1;
    }

    /*将src_file文件的读写位置便宜到500个字节处*/
    ret = lseek(fd1, 500, SEEK_SET);
    if(ret == -1){
        goto err2;
    }

        /* 读取 src_file 文件数据,大小 1KByte */
    ret = read(fd1, buffer, sizeof(buffer));
    if (ret == -1) {
        printf("Read file:test_file Failed!\r\n");
    goto err2;
}

    /*将buffer中的数据写入到test_file文件中,大小为1Kb*/
    ret = write(fd2, buffer, sizeof(buffer));
    if(ret == -1){
        printf("Write file:test_file Failed!\r\n");
        goto err2;
    }
    printf("Test:Successful\r\n");
    return 0;
err2:
    close(fd2);
err1:
    close(fd1);
    return ret;
}

        这个读写应用实现的功能如下:

①打开src_file文件
②新建test_file文件并打开
③将文件src_file的读写位置设置到500
④从sec_file文件中读1Kb的数据到缓冲buffer中
⑤将buffer中的数据写入test_file文件中

从这个简单的应用中学习一下文件I/O的基础部分

一、man命令

        在Linux 系统下,可以通过man命令来查看某一个Linux系统调用的帮助信息,man命令可以将该系统调用的详细信息显示出来,

        使用方法:man # COMMAND

        #可以代表数字1~8,一共8个章节。COMMAND表示要查询的函数

       man 2 open如下:

        从图中可以看到open函数需要包含什么头文件,以及open函数的具体用法。 

二、文件描述符

        在调用open函数打开一个文件成功的时候会返回一个非负整数,比如本应用中的fd1和fd2,文件描述符可分配的范围0~1023,其中0,1,2已经被系统占用了。
        文件描述符的分配顺序是从小到大分配的。
        当调用read/write函数对文件读写的时候,需要将文件对应的描述符传递给读写函数。

三、函数用法

          1、open

        open函数通常有以下2个基本用法:

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

pathname:字符串类型,用于标识需要打开或创建的文件,可以包含路径(绝对路径或相对路径)
flags:调用 open 函数时需要提供的标志,包括文件访问模式标志以及其它文件相关标志。
mode: 此参数用于指定新建文件的访问权限,只有当 flags 参数中包含 O_CREAT 或 O_TMPFILE 标志时才有效。

对于本应应用中flags和mode的解释,在注释中标注了

        2、write

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

fd: 文件描述符。 关于文件描述符,前面已经给大家进行了简单地讲解,这里不再重述!我们需要将进行写操作的文件所对应的文件描述符传递给 write 函数。
buf: 指定写入数据对应的缓冲区。
count: 指定写入的字节数。
返回值: 如果成功将返回写入的字节数(0 表示未写入任何字节),如果此数字小于 count 参数,这不是错误,譬如磁盘空间已满,可能会发生这种情况;如果写入出错,则返回-1

        3、read

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

fd: 文件描述符。与 write 函数的 fd 参数意义相同。
buf: 指定用于存储读取数据的缓冲区。
count: 指定需要读取的字节数。
返回值: 如果读取成功将返回读取到的字节数,实际读取到的字节数可能会小于 count 参数指定的字节数,也有可能会为 0,譬如进行读操作时,当前文件位置偏移量已经到了文件末尾。 实际读取到的字节数少于要求读取的字节数,譬如在到达文件末尾之前有 30 个字节数据,而要求读取 100 个字节,则 read 读取成功只能返回 30;而下一次再调用 read 读,它将返回 0。

        4、close

#include <unistd.h>
int close(int fd);

fd:要关闭的文件的文件描述符 

        5、lseek

             当打开文件时,会将读写偏移量设置为指向文件开始位置处,以后每次调用 read()、 write()将自动对其进行调整,以指向已读或已写数据后的下一字节

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

fd: 文件描述符。
offset: 偏移量,以字节为单位。
whence: 用于定义参数 offset 偏移量对应的参考值, 该参数为宏定义

SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算)
SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处, offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移;
SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处,同样 offset 可以为正、也可以为负,如果是正数表示往后偏移、如果是负数则表示往前偏移。

四、 运行测试

        利用gcc编译链将该应用编译并执行:

         如图所示实现了生成并拷贝内容的功能 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值