文件IO其二
Posted smallqizhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件IO其二相关的知识,希望对你有一定的参考价值。
1.文件IO
文件IO属于linux系统中关于文件操作的系统调用,对于文件的操作也是跟标准IO一样,打开文件 > 操作文件 > 关闭文件。
文件IO和标准IO的比较:
标准IO | 文件IO | |
代表打开的文件 | 文件流指针(FILE*) | 文件描述符(fd) |
打开文件/关闭文件 | fopen/fclose | open/close |
读写操作 |
fputc/fgetc fputs/fgets fwrite/fread fprintf/fscanf |
read/write |
读写操作 | fseek/rewind/ftell | lseek/dup/dip2/fcntl/stat/unlink... |
a.文件描述符
文件描述符用来代表一个打开的文件,本质上是一个非负整数,文件描述符本身并不存储任何的文件信息,只是用来对应文件表。通过文件描述符就可以找到对应的文件的信息(struct file)。
在linux中,一个程序打开的文件数量有限,默认1024个,文件描述符从大小到大分配,可以重复使用。文件描述符从0开始,其中0、1、2已经被系统占用(程序自动打开),分别代表标准输入、标准输出、错误输出,我们使用的文件描述符从3开始。
b.打开文件 open
参数:pathname 文件的路径
flags 打开的标志(多个标志用 | 连接)
mode 创建文件的权限(仅仅在创建文件的时候用,必须用),权限可以用三位8进制(0开头)表示,也可以使用宏
打开成功会返回一个新的文件描述符,失败返回 -1。
O_EXCL | 必须创建标志:和创建标志一起使用,表示要创建文件,如果文件已存在报错 |
O_TRUNC | 截断标志:打开后清空文件内容 |
O_APPEND | 追加标志:打开文件后读写位置在文件末尾 |
O_NOCTTY | 表示如果打开的是终端文件,不将终端作为会话的控制终端 |
O_NONBLOCK | 表示使用非阻塞方式 |
flags标志 | 功能 |
O_RONDLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 读写(只读、只写、读写这三个必须选一个) |
O_CREATE | 创建标志 |
c.关闭文件 close
d.读写操作
参数: fd 文件描述符
buf 读写的内存地址
count 希望读写的大小
函数执行成功后会返回读写的带下,失败返回 -1,读到末尾或者什么都没读写到就返回0。
e.非读写操作
(1)调整文件读写的位置 lseek()函数
参数: fd 要操作的文件描述符
offset 相对于基准的便宜
whence 读写位置的基准
SEEK_SET | 文件开头 |
SEEK_CUR | 当前位置 |
SEEK_END | 文件末尾 |
函数执行成功后返回调整后的读写位置距离文件开头的距离,失败则返回 -1。
(2)复制文件描述符 dup()/dup2()函数
复制文件描述符不会复制产生新的文件表条目(复制产生的描述符还是指向原来的那一条文件表条目),和重新打开不同。dup()由系统选定新的描述符(选最小未使用)的值,dup2()由调用者指定新的描述的符的值,如果指定的值已经被使用,会先关闭再使用(有安全隐患)
参数: oldfd 旧的文件描述符,newfd 新的文件描述符
(3)fcntl()函数
fcntl函数有很多功能,具体使用哪个功能由参数cmd决定,有如下几个常用的功能:
1)复制文件描述符 2)设置/获取文件描述符的标志 3)设置文件锁
参数: fd 要操作的文件描述符
cmd 功能
cmd | 功能 |
F_DUPFD | 复制文件描述符:此时需要使用第三个参数,第三个参数代表新的描述符的值,和dup2的区别在于不会强制关闭已使用的描述符,而是寻找大于等于参数值的最小未使用的描述符 |
F_SETFL/F_GETFL | 设置/获取文件描述符的标志:
设置时,只能设置O_APPEND标志,权限标志和创建标志设置无效 获取时,可以获取权限标志和O_APPEND,创建标志无法获取 |
F_SETLK/F_SETLKW/F_GETLK | 文件锁操作:
当在多个程序(进程)同时读写一个文件,有可能造成数据混乱,文件锁就是用来解决这个问题 文件锁就是在有一个程序(进程)读写文件时,对其它程序(进程)的读写操作进行限制 如何实现:一个程序(进程)读,允许其它程序(进程)读,但不允许其它程序(进程)写 --- 读锁 一个程序(进程)写,既不允许其它程序(进程)读,也不允许其它程序(进程)写 --- 写锁 文件锁是一个读写锁,其中读锁是一个共享锁,写锁是一个互斥锁 实现机制:文件锁本质上是一个标识,锁定的不是读写操作本身,而是锁定加锁操作
F_SETLK/F_SETLKW用于加锁和解锁,F_SETLK属于非阻塞方式(立即返回),F_SETLKW属于阻塞式(成功才返回) F_GETLK用于测试锁(基本不用) |
arg 可选参数,当用作文件锁功能时,arg参数应该是一个结构体(struct flock)
struct flock { ... short l_type; /* 锁类型: F_RDLCK(读锁), F_WRLCK(写锁), F_UNLCK(解锁) */ short l_whence; /* 锁定起始位置的基准: SEEK_SET, SEEK_CUR, SEEK_END */ off_t l_start; /* 锁定起始位置相对于基准的偏移 */ off_t l_len; /* 锁定的长度(字节)*/ pid_t l_pid; /* 只在F_GETLK使用,其他时候给-1 */ ... };
函数的返回值:
文件锁通常用在多程序(进程)同时访问同一个文件的场合,防止数据混乱。除此之外文件锁也可以用于后台服务程序(守护进程)的互斥,保证后台服务程序只有一份,在后台服务程序启动时加锁,加锁成功继续运行,加锁失败就直接退出
(4)获取文件信息 stat()函数
struct stat
{ dev_t st_dev; /* 文件所在硬件的设备号 */ ino_t st_ino; /* Inode 值(唯一代表一个文件) */ mode_t st_mode; /* 文件类型和文件权限 */ nlink_t st_nlink; /* 硬链接数 */ uid_t st_uid; /* 所有者用户ID*/ gid_t st_gid; /* 所有者的组ID */ dev_t st_rdev; /* 设备号 (仅仅设备文件) */ off_t st_size; /* 文件大小*/ blksize_t st_blksize; /* 块的大小 */ blkcnt_t st_blocks; /* 块的个数 */ /* Since Linux 2.6, the kernel supports nanosecond precision for the following timestamp fields. For the details before Linux 2.6, see NOTES. */ struct timespec st_atim; /* 最后访问时间 */ struct timespec st_mtim; /* 最后修改时间*/ struct timespec st_ctim; /* 最后状态修改时间 */ #define st_atime st_atim.tv_sec /* Backward compatibility */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
参数:pathname 文件的路径
satbuf 传出的文件信息
函数执行成功就会返回0,失败则返回 -1。
PS:fstat函数用文件描述符代表一个文件,lstat与stat类似,唯一的区别是当文件是一个软连接文件的时候,stat获取的是软连接指向的文件信息,lstat获取的是软连接本身的信息。
(5)测试文件权限和是否存在 access()函数
参数: pathname 文件路径
mode 测试内容
F_OK 文件是否存在
R_OK 读权限
W_OK 写权限
X_OK 执行权限
函数返回0表示这个文件存在/具有这个权限,-1表示没有或者出错。
(6)修改权限屏蔽字 umask
传入新的权限屏蔽字,返回旧的权限屏蔽字(用于处理完之后的恢复)
(7)其他函数
chmod()修改权限
mkdir()创建目录
rmdir()删除空目录
unlink()删除文件
remove()删除文件/空目录
rename()更改文件名
chdir()切换工作目录
truncat()指定文件的大小
getcwd()获取当前绝俗路径
PS:在C语言中可以调用system函数来执行命令行命令
PS:如果有错误麻烦指出来,大家互相学习 0-0
以上是关于文件IO其二的主要内容,如果未能解决你的问题,请参考以下文章
java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段
编写一个程序, 将 a.txt 文件中的单词与 b.txt 文件中的 单词交替合并到 c.txt 文件中, a.txt 文件中的单词用回车符 分隔, b.txt 文件中用回车或空格进行分隔。(代码片段
csharp C#代码片段 - 使类成为Singleton模式。 (C#4.0+)https://heiswayi.github.io/2016/simple-singleton-pattern-us
是否有一种方法可以将实时记录的音频片段连续发送到Flutter.io中的后端服务器?
Android android.view.InflateException Binary XML 文件第 16 行:膨胀类片段时出错