文件IO
一、概念
在posix(可移植操作系统接口)中定义的一组输入输出的函数
二、 特点
- 没有缓冲机制,每次操作都会经过系统调用,效率比较低
- 围绕文件描述符进行操作,文件描述符是非负整数, 0、1、2.....
- 默认打开三个文件描述符,0(标准输入)、1(标准输出)、2(标准错误)
- 除目录外其他任意类型文件都可以操作
三、函数
3.1打开文件 open
int open ( const char * pathname , int flags );功能:打开文件
参数:
pathname:文件路径名
flags:打开文件的方式
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
O_CREAT:创建
O_TRUNC:清空
O_APPEND:追加
返回值:
成功:文件描述符
失败:-1
示例:
当打开方式为:O_CREAT的时候,才会需要使用第三个参数
补充:
- 当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限 ,open(file, xx|O_CREAT|xx, 0666);
- 实际创建出来的文件权限为指定权限值&(~umask) //umask为文件权限掩码,通过umask命令可以查看
- 打开文件方式对应表:
标准IO
文件IO
r
O_RDONLY
r+
O_RDWR
w
O_WRONLY|O_TRUNC|O_CREAT
w+
O_RDWR|O_TRUNC|O_CREAT
a
O_APPEND|O_CREAT|O_WRONLY
a+
O_RDWR|O_APPEND|O_CREAT
3.2关闭文件 close
int close ( int fd );
3.3读文件 read
ssize_t read ( int fd , void * buf , size_t count );功能:从一个已打开的可读文件中读取数据
参数:
fd 文件描述符
buf 存放位置
count 期望的个数
返回值:
成功:实际读到的个数
返回-1:表示出错,并设置errno号
返回0:表示读到文件结尾
3.4写文件 write
ssize_t write ( int fd , const void * buf , size_t count );功能:向指定文件描述符中,写入 count个字节的数据。
参数:
fd 文件描述符
buf 要写的内容
count 期望值
返回值:
成功:实际写入数据的个数
失败 : -1
3.5文件定位操作
off_t lseek ( int fd , off_t offset , int whence );功能:设定文件的偏移位置
参数:
fd:文件描述符
offset偏移量
正数:向文件结尾位置移动
负数:向文件开始位置
whence 相对位置
SEEK_SET 开始位置
SEEK_CUR 当前位置
SEEK_END 结尾位置
返回值:
成功:文件的当前位置
练习:实现如下功能
1-- 打开一个文件,不存在创建,存在清零
2-- 向文件中第 10 位置处写一个字符,
3-- 在文件此时的位置,后 20个位置处,写一行字符串hello进去
4-- 求文件的长度。
#include "head.h"
int main(int argc, char const *argv[])
{
int fd;
char buf[32] = "";
fd = open("./test.c", O_RDWR | O_TRUNC | O_CREAT);
if (fd < 0)
{
perror("open err");
return -1;
}
lseek(fd, 10, SEEK_SET);
write(fd, "a", 1);
lseek(fd, 20, SEEK_CUR);
write(fd, "hello", 5);
off_t off = lseek(fd, 0, SEEK_END);
printf("%ld\n", off);
close(fd);
return 0;
}
3.6文件属性获取
int stat ( const char * path , struct stat * buf );功能:获取文件属性
参数:
path:文件路径名
buf:保存文件属性信息的结构体
返回值:
成功:0
失败:-1
struct stat
{
dev_t st_dev; /* 设备ID */
ino_t st_ino; /* inode号 */
mode_t st_mode; /* 文件类型和权限 */
nlink_t st_nlink; /* 硬链接数 */
uid_t st_uid; /* 用户ID */
gid_t st_gid; /* 组ID */
off_t st_size; /* 大小 */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后状态改变时间 */
};
示例:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
struct stat st;
stat("test.c", &st);
printf("%ld\n", st.st_ino);
printf("%ld\n", st.st_size);
printf("%ld\n", st.st_nlink);
// 文件类型判断
// __S_IFMT:文件类型掩码 S_IFREG:普通文件 S_IFDIR:目录
if((st.st_mode & __S_IFMT) == S_IFREG)
putchar('-');
else if((st.st_mode & __S_IFMT) == S_IFDIR)
putchar('d');
// 判断文件权限
// 用户读权限
if((st.st_mode & S_IRUSR) > 0)
putchar('r');
else
putchar('-');
// 用户写权限
if((st.st_mode & S_IWUSR) > 0)
putchar('w');
else
putchar('-');
// 最后一次修改的时间
// 这个得到的是秒的形式
// 我们可以借助localtime函数
printf("%ld\n", st.st_mtime);
// 用户名获取
getpwuid();
// 获取组名
getgrgid();
return 0;
}
3.7目录操作
围绕目录流进行操作,DIR *
DIR *opendir(const char *name);
功能:获得目录流
参数:要打开的目录
返回值:成功:目录流
失败:NULL
struct dirent *readdir(DIR *dirp);
功能:读目录
参数:要读的目录流
返回值:成功:读到的信息
失败或读到目录结尾:NULL
返回值为结构体,该结构体成员为描述该目录下的文件信息
struct dirent {
ino_t d_ino; /* 索引节点号*/
off_t d_off; /*在目录文件中的偏移*/
unsigned short d_reclen; /* 文件名长度*/
unsigned char d_type; /* 文件类型 */
char d_name[256]; /* 文件名 */
};
int closedir(DIR *dirp);
功能:关闭目录
参数:dirp:目录流
示例:
四、标准IO和文件IO的区别
标准IO | 文件IO | |
概念 | 在C库中定义的一组输入输出的函数 | 在posix中定义 |
特点 |
|
|
函数 | 打开文件:fopen 关闭文件:fclose 读写文件:fgetc/fputc 文件定位:fseek/rewind/ftell | 打开文件:open 关闭文件:close 读写文件:read/write 文件定位:lseek |