Linux文件IO常用函数

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,若文件不存在则可创建
参数:
    pathname:文件路径名
    flags:打开文件的方式,必选项:O_RDONLY、O_WRONLY、O_RDWR
    mode:新建文件时指定文件的权限,此参数仅在文件不存在时生效
返回值:
    成功:打开文件的文件描述符
    失败:-1
*/

flags详细说明:

必选项:

取值含义
O_RDONLY以只读的方式打开
O_WRONLY以只写的方式打开
O_RDWR以可读、可写的方式打开

可选项:(和必选项按位或)

取值含义
O_CREAT若文件不存在则创建,此选项需要指定mode参数说明文件权限
O_EXCL若同时指定了O_CREAT,且文件已存在,则出错
O_TRUNC若文件存在,则清空文件内容
O_APPEND以追加的方式写文件
O_NONBLOCK对于设备文件,以非阻塞方式打开

mode权限:

取值(八进制)含义
00700文件所有者:读、写、执行
00400文件所有者:读
00200文件所有者:写
00100文件所有者:执行
00070文件所有者同组:读、写、执行
00040文件所有者同组:读
00020文件所有者同组:写
00010文件所有者同组:执行
00007其他组:读、写、执行
00004其他组:读
00002其他组:写
00001其他组:执行

2. close函数

函数原型:

#include<unistd.h>

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

 open和close使用示例:

void test() {
    int fd = -1;

    // 以只读的方式打开一个文件,若文件不存在则报错
    fd = open("txt", O_RDONLY);

    // 以只写的方式打开一个文件,若文件不存在则新建;文件存在则直接打开,同时mode参数无效。
    fd = open("txt", O_WRONLY | O_CREAT, 0644);

    // 以只写的方式打开一个文件,若文件不存在则新建;文件存在则报错。
    fd = open("txt", O_WRONLY | O_CREAT | O_EXCL, 0644);

    // 以只写的方式打开一个文件,若文件不存在则新建;文件存在则清空文件内容。
    fd = open("txt", O_WRONLY | O_TRUNC |O_CREAT, 0644);

    // 以只写和追加的方式打开一个文件,若文件不存在则报错。
    fd = open("txt", O_WRONLY | O_APPEND);

    if (-1 == fd) {
        perror("open");
        return 1;
    }

    // 文件描述符 0 1 2 已被使用,会分配一个最小的空闲文件描述符
    printf("fd = %d\n", fd);
    close(fd);
}

3. write函数

函数原型:

#include<unistd.h>

ssize_t write(int fd, const void* buf, size_t count);
/*
功能:
    将buf中count个字节的数据写到文件fd
参数:
    fd:写入的目标文件描述符
    buf:写入数据的首地址
    count:写入数据的字节数
返回值:
    成功:实际写入数据的字节数
    失败:-1
*/

write使用示例:

void test() {
    int fd = -1;
    int ret = -1;
    char* str = "Hello";

    // 1. 只写的方式打开一个文件
    fd = open("txt", O_WRONLY | O_CREAT, 0644);
    if (-1 == fd) {
        perror("open");
        return 1;
    }
    printf("fd = %d\n", fd);

    // 2. 写文件
    ret = write(fd, str, strlen(str));
    if (-1 == ret) {
        perror("write");
        return 1;
    }
    printf("实际写入:%d个字节.\n", ret);

    // 3. 关闭文件
    close(fd);
}

4. read函数

函数原型:

#include<unistd.h>

ssize_t read(int fd, void* buf, size_t count);
/*
功能:
    从文件fd将count个字节的数据读入buf
参数:
    fd:被读取文件的文件描述符
    buf:内存缓冲区首地址
    count:读取的字节数
返回值:
    成功:实际读取的字节个数
    失败:-1
*/

read使用示例:

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

#define SIZE 128

int test() {
    int fd = -1;
    int ret = -1;
    char buf[SIZE];

    // 1. 以只读的方式打开一个文件
    fd = open("txt", O_RDONLY);
    if (-1 == fd) {
        perror("open");
        return 1;
    }
    printf("fd = %d\n", fd);

    // 读文件
    memset(buf, 0, SIZE); // 数组清零
    // 返回实际读取的字节数,这里读取了5个字节
    ret = read(fd, buf, SIZE);
    if (-1 == ret) {
        perror("read");
        return 1;
    }
    printf("read len: %d. %s\n", ret, buf);  // read len: 5. Hello
}

非阻塞read使用示例:

(注意:非阻塞是文件属性,而不是read函数属性)

int test() {
    /*
    以非阻塞、读的方式打开当前终端。 /dev/tty当前终端设备
    */
    int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);
    char buf[10];
    int n;

    n = read(fd, buf, sizeof(buf));
    if (n < 0) {
        // EAGAIN:若非阻塞,但是没有数据可读。此时全局变量errno被设置为EAGAIN。
        if (errno != EAGAIN) {
            perror("read /dev/tty");
            return -1;
        }
        printf("没有数据.\n");
    }
    return 0;
}

5. lseek

(1)所有打开的文件都有一个当前文件偏移量(current file offset, cfo),cfo通常为非负整数,表示文件起始位置到当前位置的偏移字节数。

(2)读写操作通常开始于cfo,并使cfo增大,增量为读写的字节数。除非以O_APPEND的方式打开文件,其余方式打开文件cfo被初始化为0.

函数原型:

#include<sys/types.h>
#include<unistd.h>

off_t lseek(int fd, off_t offset, int whence);
/*
功能:
    从文件fd的whence位置开始偏移offset个字节
参数:
    fd:文件描述符
    offset:从whence位置开始的偏移量。
            正数:从whence位置向右移动; 负数:从whence位置向左移动。
            若向左偏移超过了文件起始位置,则出错返回;
            若向右偏移超过了文件末尾位置,则再次写入时将增大文件大小。
    whence:
        SEEK_SET:从文件起始位置偏移offset个字节
        SEEK_CUR:从文件当前位置偏移offset个字节
        SEEK_END:从文件末尾位置偏移offset个字节
返回值:
    成功:返回新的偏移量
    失败:-1
*/

lseek使用示例:

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

#define SIZE 128

int test() {
    int fd = -1;
    int ret = -1;
    char buf[SIZE];

    // 1. 打开文件
    fd = open("txt", O_RDWR | O_CREAT, 0644);
    if (-1 == fd) {
        perror("open");
        return 1;
    }
    printf("fd = %d\n", fd);

    // 2. lseek操作
    write(fd, "ABCD", 4);  // 此时txt文件为4字节

    // 从文件起始位置偏移10个字节。
    // 若只偏移,后续没有从偏移的新位置的写操作,则文件大小不变,仍为4字节
    ret = lseek(fd, 10, SEEK_SET);
    if (-1 == ret) {
        perror("lseek");
        return 1;
    }

    // 从偏移位置(距文件起始位置10字节)写入5字节,此时文件大小15字节
    // 此时txt中数据为:ABCD^@^@^@^@^@^@12345
    // ^@表示ascii为0的字符
    ret = write(fd, "12345", 5);
    if (-1 == ret) {
        perror("write");
        return 1;
    }

    memset(buf, 0, SIZE);

    // 无法读取,因为文件偏移位置在末尾
    ret = read(fd, buf, SIZE);
    if (-1 == ret) {
        perror("read");
        return 1;
    }
    printf("read buf: %s\n", buf);  // 无数据

    // 将文件偏移到起始位置
    ret = lseek(fd, 0, SEEK_SET);
    if (-1 == ret) {
        perror("lseek");
        return 1;
    }

    // 可读出文件中的数据:ABCD, 因为遇到ascii为0的字符就认为文件结束
    ret = read(fd, buf, SIZE);
    if (-1 == ret) {
        perror("read");
        return 1;
    }
    printf("read buf: %s\n", buf);  // ABCD

    // 3. 关闭文件
    close(fd);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的马师兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值