Linux文件操作open、write、read、close、lseek、sync

1、open

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

描述:打开指定路径的文件,返回一个文件描述符。
参数:pathname文件路径名;flags打开文件的方式;mode设置文件的权限。
(1)参数2(打开方式 )
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
O_CREAT 如果文件不存在,则创建该文件,并使用第3个参数设置权限,如果文件存在 ,则只打开文件;
O_EXCL 如果同时使用O_CREAT而且该文件又已经存在时,则返回错误, 用途:以防止多个进程同时创建同一个文件;
O_APPEND 尾部追加方式(打开后,文件指针指向文件的末尾);
O_TRUNC 若文件存在,则长度被截为0,属性不变.
例: open(“/dev/hello”, O_RDONLY|O_CREAT|O_EXCL, 0777)
多个设置可用 “|” 进行分割。

(2)参数3 (设置权限)
当参数2使用了O_CREAT时,就得使用参数3
S_I(R/W/X)(USR/GRP/OTH)
S_IRWXU 00700 用户拥有 读 写 执行 权限
S_IRUSR 00400 用户拥有 读 权限
S_IWUSR 00200 用户拥有 写 权限
S_IXUSR 00100 用户拥有 执行 权限
S_IRWXG 00070 同组拥有 读 写 执行 权限
S_IRGRP 00040 同组拥有 读 权限
S_IWGRP 00020 同组拥有 写 权限
S_IXGRP 00010 同组拥有 执行 权限
S_IRWXO 00007 其他人拥有 读 写 执行 权限
S_IROTH 00004 其他人拥有 读 权限
S_IWOTH 00002 其他人拥有 写 权限
S_IXOTH 00001 其他人拥有 执行 权限
可以发现,读写执行权限,是由 读 + 写 + 执行 而得来的;
例如用户的 00700,是由 00400 + 00200 + 00100 而得来的。
例:
S_IRUSR | S_IWUSR 文件的所有者对该文件可读可写
(八进制表示法)00600 文件的所有者对该文件可读可写
多个设置可用 “|” 进行分割。
返回值:
成功:返回新的文件描述符(返回的文件描述符是该进程未打开的最小的文件描述符);
失败:-1,并且设置错误编号 errno ,可用( strerror(errno) ) 查看。

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

int main(void) {
    int fd = 0;
    char fileName[] = "test.txt";
    // 读写,如果文件不存在则创建,如果文件存在则报错(O_EXCL);
    // 设置本用户拥有读写执行权限,同组用户拥有读写权限,其他人拥有读权限
    // fd = open(fileName, O_RDWR|O_CREAT|O_EXCL, 00764); // 可以使用数字代替参数三
    fd = open(fileName, O_RDWR|O_CREAT|O_EXCL, S_IRWXU|S_IRGRP|S_IWGRP|S_IROTH);
    if (-1 == fd) {
        fprintf(stderr, "open %s fail. reason: %s\n", fileName, strerror(errno));
        exit(-1);
    }
    printf("open %s successful!\n", fileName);
    // 关闭文件
    close(fd);
    return 0;
}

2、write

ssize_t write (int fd, const void *buf, size_t count);

描述:write()从指向buf的缓冲区向文件描述符fd引用的文件写入count个字节。
参数:
fd:文件描述符;
buf:需要写入的数据;
count:指定最多写入的大小;
返回值:
成功: 返回写入的字节数;
失败: 返回 -1,并且设置错误编号 errno ,可用( strerror(errno) ) 查看。

注意:是从文件的当前指针位置写入!文件刚打开时,文件的位置指针指向文件头。

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>

#define W_LEN   1024
int main(void) {
    int ret = 0;
    int fd = -1;
    char fileName[] = "test.txt";
    char buf[W_LEN] = "这是要写入的内容:Hello write!";
    // 打开以文件,只写方式打开,不懂00764是什么意思上面open介绍
    fd = open(fileName, O_WRONLY|O_CREAT|O_EXCL, 00764);
    if (-1 == fd) {
        fprintf(stderr, "open %s fail. reason: %s\n", fileName, strerror(errno));
        exit(-1);
    }
    // 往文件中写入数据
    ret = write(fd, buf, strlen(buf));
    if(-1 == ret) {
        fprintf(stderr, "write error. reason: %s\n", strerror(errno));
        exit(-2);
    }
    printf("write successful! write lenght: %d\n", ret);
    close(fd);
    return 0;
}

3、 read

ssize_t read (int fd, void *buf, size_t count);

描述:read()尝试从文件描述符fd上读取数据放入buf中,读count字节。
参数:
fd:文件描述符;
buf:存储读取到的数据,一般传char *类型或字符数组;
count: 指定最多读取的大小;表示最多能接受的字节数,而不是指一定要读取的字节数;
返回值:
成功: 返回读取到的字节数;如果返回 0,表示文件读完了;
失败: 返回 -1,并且设置错误编号 errno ,可用( strerror(errno) ) 查看。

注意:是从文件的当前指针位置读取!文件刚打开时,文件的位置指针指向文件头。

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>

#define R_LEN   1024
int main(void) {
    int ret = 0;
    int fd = -1;
    char fileName[] = "test.txt";
    char buf[R_LEN] = { '\0' };
    // 打开以文件,只读方式打开,不懂00764是什么意思上面open介绍
    fd = open(fileName, O_RDONLY, 00764);
    if (-1 == fd) {
        fprintf(stderr, "open %s fail. reason: %s\n", fileName, strerror(errno));
        exit(-1);
    }
    // 从文件中读取数据
    ret = read(fd, buf, sizeof(buf));
    if(-1 == ret) {
        fprintf(stderr, "read error. reason: %s\n", strerror(errno));
        exit(-2);
    }
    printf("read successful! read lenght: %d\n", ret);
    printf("%s\n", buf);
    close(fd);
    return 0;
}

4、 close

int close (int fd);

描述:close()关闭一个文件描述符,这样它就不再引用任何文件,可以被重用。
参数:
fd:文件描述符;
返回值:
成功: 返回 0;
失败: 返回 -1,并且设置错误编号 errno ,可用( strerror(errno) ) 查看.
当出现错误后,错误形式有三种:
(1). EBADF fd不是有效的打开文件描述符;
(2). EINTR close()调用被一个信号打断;
(3). EIO I/O错误.

#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    int ret = -1;
    int fd = 0;
    char fileName[] = "test.txt";
    fd = open(fileName, O_RDWR|O_CREAT, 00764);
    if (-1 == fd) {
        fprintf(stderr, "open %s fail. reason: %s\n", fileName, strerror(errno));
        exit(-1);
    }
    printf("open %s successful!\n", fileName);
    // 关闭文件
    ret = close(fd);
    if (-1 == ret) {
        int err = errno;
        fprintf(stderr, "close error. reason: %s\n", strerror(err));
        // 错误原因
        if (EBADF == err) {
            printf("fd不是有效的打开文件描述符\n");
        } else if (EINTR == err) {
            printf("close()调用被一个信号打断\n");
        } else if (EIO == err) {
            printf("I/O错误\n");
        }
        exit(-2);
    }
    printf("close fd successful!\n");
    return 0;
}

5、 lseek

off_t lseek (int fd, off_t offset, int whence);

描述:移动文件光标偏移。
参数:
fd:文件描述符;
offset:文件指针(光标)移动的大小;往文件头部移动设负数,往文件尾部移动设正数;
whence: 文件指针(光标)移动的依据;
(1)文件指针移动的依据:
SEEK_SET 相对于文件头部开始偏移;
例:移动文件指针(光标)到第100个位置处
sleek(fd, 100, SEEK_SET); // 直接从开头位置往文件尾部移动100即可
SEEK_CUR 从当前位置开始偏移;
例:文件指针已经再100位置了,现在把他移动到80的位置
sleek(fd, -20, SEEK_CUR); // 在文件指针当前位置往文件头部移动-20个位置即可
SEEK_END 相对于文件尾部开始偏移;
例:文件指针已经再80位置了,现在把他移动到倒数第5个位置
sleek(fd, -5, SEEK_END); // 直接在文件尾部往文件头部移动-5个位置即可
返回值:
成功: 返回 移动后文件指针的所在位置;
失败: 返回 -1,并且设置错误编号 errno ,可用( strerror(errno) ) 查看。

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>

#define R_LEN           1024
#define READ_LEN        100
int main(void) {
    int ret = 0;
    int fd = -1;
    char fileName[] = "test.txt";
    char buf[R_LEN] = { '\0' };
    fd = open(fileName, O_RDONLY);
    if (-1 == fd) {
        fprintf(stderr, "open %s fail. reason: %s\n", fileName, strerror(errno));
        exit(-1);
    }
    // 从文件头部往文件尾部移动100位置
    ret = lseek(fd, 100, SEEK_SET);
    if (-1 == ret) {
        fprintf(stderr, "lseek error. reason: %s\n", strerror(errno));
        exit(-2);
    }
    // 从文件中读取100个字节
    ret = read(fd, buf, READ_LEN);
    if(-1 == ret) {
        fprintf(stderr, "read error. reason: %s\n", strerror(errno));
        exit(-3);
    }
    printf("read successful! read lenght: %d\n", ret);
    printf("%s\n", buf);
    close(fd);
    return 0;
}

6、 fsync
Linux同步机制。
简单来讲,使用上面介绍的write后,或者做其他对文件有修改的操作后,需要进行同步,将数据从内核缓冲区写入磁盘;否则如果断电或系统宕机,即使已经调用了write或fwrite函数,数据都还没有写入磁盘。
6.1. sync

 void sync(void);

描述:将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束! sync不会执行失败!
6.2. fsync

  int fsync(int fd);        // 推荐使用!

描述:fsync()将文件描述符fd引用的文件(即修改的缓冲区缓存页)的所有修改的内核数据传输(“刷新”)到磁盘设备(或其他永久存储设备),以便即使在系统崩溃或重新启动后也可以检索所有更改的信息。这包括写入磁盘缓存或刷新磁盘缓存(如果存在的话)。他会一直阻塞,直到执行完毕!
参数:
fd: 文件描述符;
返回值:
成功: 返回 0;
失败: 返回 -1,并且设置错误编号 errno ,可用( strerror(errno) ) 查看。

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

int main(void) {
    char *filename = "test.txt";
    int fd = open(filename, O_RDWR);
    char buff[64] = "hello world";
    write(fd, buff,sizeof(buff));
    fsync(fd);
    close(fd);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值