1.什么是文件IO
1.1 概念
又称系统IO,是系统调用,是操作系统提供的函数接口
posix中定义的一组用于输入输出的函数
1.2 特点
- 没有缓冲机制,每次调用都会引起系统调用
- 围绕文件描述符进行操作,非负整数(>=0),依次分配
- 文件IO默认打开三个文件描述符,分别是0(标准输入),1(标准输出),2(标准错误)
- 操作除了目录以外的任意类型的文件: b c - l s p
- 可移植性相对较弱
1.3 操作
- 打开文件:open
- 关闭文件: close
- 读写操作: read、write
- 定位操作: lseek
2.函数接口
2.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选项时,需要给open函数传递第三个参数,指定创建文件的权限
int open(const char *pathname, int flags, mode_t mode);
最后权限 = mode & (~umask)
例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
int fd;
//fd = open("a.c", O_RDONLY); //r 没有文件会报错
fd = open("a.c", O_WRONLY | O_CREAT | O_TRUNC, 0666); //w
if (fd < 0)
{
perror("open err");
return -1;
}
printf("fd :%d\n", fd);
return 0;
}
通过ls -l a.c命令可以查看创造出来的文件权限是0664
指定的权限0666(8进制) 最终权限: 0666 & (~umask) = 0666 & (~0002)=0666 & 0775 = 0664
注意:通过umask命令可以查看umask文件权限掩码
思考:文件IO和标准IO的打开方式的对应关系
标准IO | 文件IO |
r | O_RDONLY 只读 |
r+ | O_RDWR 可读可写 |
w | O_WRONLY | O_CREAT|O_TRUNC, 0777 只写,不存在创建,存在则清空 |
w+ | O_RDWR | O_CREAT|O_TRUNC, 0777 可读可写,不存在创建,存在则清空 |
a | O_WRONLY | O_CREAT| O_APPEND, 0777 只写,不存在创建,存在追加 |
a+ | O_RDWR | O_CREAT| O_APPEND, 0777 可读可写,不存在创建,存在追加 |
注意:有O_CREAT需要加第三个参数表示权限
2.2 关闭文件
int close(int fd);
功能:关闭文件
参数:fd:文件描述符
2.3 读写文件read/write
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:从一个已打开的可读文件中读取数据
参数: fd 文件描述符
buf 存放位置
count 期望的个数
返回值:成功:实际读到的个数(小于期望值说明实际没这么多)
返回0:表示读到文件结尾
返回-1:表示出错,并设置errno号
ssize_t write(int fd, const void *buf, size_t count);
功能:向指定文件描述符中,写入 count个字节的数据。
参数:fd 文件描述符
buf 要写的内容
count 期望写入字节数
返回值:成功:实际写入数据的个数
失败 : -1
fgets --> NULL末尾或失败
fread --> 0 末尾或失败
read --> 0末尾 -1失败
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
fd = open("a.c", O_RDWR); //r+
if (fd < 0)
{
perror("open err");
return -1;
}
printf("fd :%d\n", fd);
char buf[32] = "";
read(fd, buf, 5);
printf("%s\n", buf);
write(fd, "88888", 5);
close(fd);
return 0;
}
2.4 文件定位操作 lseek
off_t lseek(int fd, off_t offset, int whence);
功能:设定文件的偏移位置
参数:fd:文件描述符
offset: 偏移量
正数:向文件结尾位置移动
负数:向文件开始位置
whence: 相对位置
SEEK_SET 开始位置
SEEK_CUR 当前位置
SEEK_END 结尾位置
补充:和fseek一样其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2.
返回值:成功:文件的当前位置
失败:-1
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
fd = open("a.c", O_RDWR); //r+
if (fd < 0)
{
perror("open err");
return -1;
}
printf("fd :%d\n", fd);
//从开头往后偏移10个字节
lseek(fd, 10, 0);
write(fd, "a", 1);
off_t off = lseek(fd, 0, 2); //利用定位到末尾求出长度
printf("%ld\n", off); //11
close(fd);
return 0;
}
标准IO和文件IO总结
标准IO | 文件IO | |
概念 | C库中定义一组用于输入输出的函数接口 | posix中定义的一组用于输入输出的函数接口 |
特点 |
|
|
函数 | 打开文件:fopen 关闭文件: fclose 读文件:fgets/fread 写文件:fputs/fwrite 定位操作:rewind/fseek/ftell | 打开文件:open 关闭文件:close 读文件: read 写文件:write 定位操作:lseek |