文件IO
什么是文件IO
1.1 概念
又称为系统IO,是系统调用,是操作系统提供的函数接口。
posix中定义的一组用于输入输出的函数。
POSIX接口 (英语:Portable Operating System Interface)可移植操作系统接口
1.2 特点
- 没有缓冲机制,每次调用都会引起系统调用。
- 围绕文件描述符进行操作,非负整数(>=0),依次分配
- 文件IO默认打开了三个文件描述符,分别是0(标准输入)、1(标准输出)、2(标准错误)
- 操作除了目录(d类型)文件的任意其他类型文件:b c - l s p
问题:打开三个文件,描述符分别是:3 4 5
关闭4以后,重新打开这个文件,文件描述符是几?
答:还是4
问题:一个进程的文件描述符最大到几?最多能打开多少个文件描述符?最多能打开多少个文件
答: 一个进程的文件描述符最大到1023(0-1023),最多能打开1024个文件描述符,最多能打开1024-3=1021个文件
1.3 操作
打开文件:open
关闭文件:close
读写操作:read、write
定位操作:lseek
函数接口
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
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
例如:O_WRONLY|O_CREAT|O_TRUNC ==> "w" 可写,不能存在时创建,存在则清空
当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限
int open(const char *pathname, int flags, mode_t mode);
最后权限=创建出来的文件指定权限值&(~umask)
例如:指定权限为0666(8进制)
最终权限为0666&(~umask) = 0666&0775 = 0664
#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);
fd = open("./a.c",O_WRONLY|O_CREAT|O_TRUNC,0777);
if (fd < 0)
{
perror("open err");
return -1;
}
printf("fd:%d\n", fd);
return 0;
}
标准IO | 文件IO |
r | O_RDONLY 只读 |
r+ | O_RDWR 可读可写 |
w | O_WRONLY|O_CREAT|O_TRUNC,0666 只写,不存在创建,存在清空 |
w+ | O_RDWR|O_CREAT|O_TRUNC,0666 可读可写,不存在创建,存在清空 |
a | O_WRONLY|O_CREAT|O_APPEND,0666 只写,不能存在创建,存在追加 |
a+ | O_RDWR|O_CREAT|O_APPEND,0666 可读可写,不存在创建,存在追加 |
注意:有O_CREAT的时候需要加第三个参数代表权限
2.2 关闭文件
int close(int fd);
功能:关闭文件
参数:fd:文件描述符
2.3 读写文件
2.3.1 读文件
ssize_t read(int fd, void *buf, size_t count);
功能:从一个已打开的可读文件中读取数据
参数: fd 文件描述符
buf 存放位置
count 期望的个数
返回值:成功:实际读到的个数(小于期望值说明实际没这么多)
返回0:表示读到文件结尾
返回-1:表示出错,并设置errno号
f
g
e
t
c
-
>
失败
和
末尾
:
E
O
F
| EOF |
fgets ->失败和末尾:NULL | NULL |
fread ->失败和末尾:0 | 0 |
read ->失败:;末尾: | -1 , 0 |
2.3.2 写文件
ssize_t write(int fd, const void *buf, size_t count);
功能:向指定文件描述符中,写入 count个字节的数据。
参数:fd 文件描述符
buf 要写的内容
count 期望写入字节数
返回值:成功:实际写入数据的个数
失败 : -1
//返回值小于期望值是错误行为,可能磁盘满了无法再写。
练习:文件IO实现cp功能。cp 源文件 新文件名
//文件IO实现cp功能。cp 源文件 新文件名
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
//判断
if (argc != 3)
{
printf("format:%s <srcfile> <destfile>\n", argv[0]);
return -1;
}
//打开文件
int fd_src = open(argv[1], O_RDONLY);
int fd_dest = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0777);
//容错判断
if (fd_src < 0 || fd_dest < 0)
{
printf("open err\n");
return -1;
}
char buf[999] = "";
ssize_t n = 0;
//循环读文件
while (n = read(fd_src, buf, 999))
{
write(fd_dest, buf, n);
}
//关闭文件
close(fd_src);
close(fd_dest);
return 0;
}
2.4 文件定位操作
off_t lseek(int fd, off_t offset, int whence);
功能:设定文件的偏移位置
参数:fd:文件描述符
offset: 偏移量
正数:向文件结尾位置移动
负数:向文件开始位置
whence: 相对位置
SEEK_SET 开始位置
SEEK_CUR 当前位置
SEEK_END 结尾位置
头文件:
#include <sys/types.h>
#include <unistd.h>补充:和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 argc, char const *argv[])
{
//open 打开文件
int fd;
char buf[33] = "";
fd = open("t1.txt", O_WRONLY | O_CREAT | O_TRUNC, 0777); //w
//fd = open("t1.txt", O_WRONLY | O_CREAT | O_TRUNC, 0777); // w+
//fd = open("t1.txt", O_RDONLY); //r
//fd = open("t1.txt", O_RDWR); //r+
//fd = open("t1.txt", O_WRONLY | O_APPEND | O_CREAT, 0777); //a
//fd = open("t1.txt", O_RDWD | O_APPEND | O_CREAT, 0777); //a+
if (fd < 0)
{
perror("open err");
return -1;
}
printf("fd:%d\n", fd);
//read 从一个已打开的可读文件中读取数据
//read(fd, buf, 10);
//printf("buf:%s\n", buf);
//write 向指定文件描述符中,写入 count个字节的数据
write(fd, "world", 5);
write(fd, " hello", 6);
//lseek 设定文件的偏移位置
int l = lseek(fd, 0, 2);
printf("%d\n", l); //利用结尾偏移求出长度
close(fd);
return 0;
}
练习:向文件中第 10 位置后面写一个字符,在文件此时的位置,后第 20个位置处,写一行字符串hello进去,求此时文件的长度。
//练习:向文件中第 10 位置后面写一个字符,在文件此时的位置,
//后第 20个位置处,写一行字符串hello进去,求此时文件的长度。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
int fd = open("t1.txt", O_RDWR);
if (fd < 0)
{
printf("open err\n");
return -1;
}
lseek(fd, 10, 0);
write(fd, "A", 1);
lseek(fd, 20, 1);
write(fd, "hello", 5);
printf("%ld\n", lseek(fd, 0, 2));
return 0;
}
标准IO和文件IO总结
标准IO | 文件IO | |
概念 | C库中定义的一组用于输入输出的函数 | posix中定义的一组输入输出的函数 |
特点 |
|
|
函数 | 打开文件:fopen\freopen 关闭文件:fclose 读文件:fgetc\fgets\fread 写文件:fputc\fputs\fwrite 定位操作:rewind\fseek\ftell | 打开文件:open 关闭文件:close 读文件:read 写文件:write 定位操作:lseek |