1.文件IO
介绍:(系统IO、系统调用)
POSIX(可移植操作系统接口)定义的一组函数,不提供缓冲机制,每次读写操作都引起系统调用,核心概念是文件描述符,访问各种文件类型,Linux下,标准IO基于文件IO实现
操作 | 标准IO | 文件IO |
---|---|---|
打开 | fopen,freopen,fdopen | open |
关闭 | fclose | close |
读 | getc,fgetc,getchar,fgets,gets,fread | read |
写 | putc,fputc,putchar,fputs,puts,fwrite | write |
文件描述符:
每个打开的文件都对应一个文件描述符
文件描述符是一个非负整数。Linux为程序中每个打开的文件分配一个文件描述符
文件描述符从0开始分配,依次递增
文件IO操作通过文件描述符来完成
2.文件IO打开使用
文件IO——open
open函数用来创建或打开一个文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
int creat(const char *pathname, mode_t mode);
成功时返回文件描述符,出错时返回EOF
- 打开文件时使用两个参数
- 创建文件时第三个参数指定新文件的的权限,(只有在建立新文件时有效)此外真正创建文件的权限会受到umask值影响,实际权限是mode-umasks
- 可以打开设备文件,但是不能创建设备文件(创建设备文件,需要先申请设备号,定义声明设备对象等操作后,用mknod创建设备文件)
模式对比:
标准IO | 文件IO |
---|---|
r | O_RDONLY |
r+ | O_RDWR |
w | O_WRONLY 或 O_CREAT 或 O_TRUNC |
w+ | O_RDWR 或 O_CREAT 或 O_TRUNC |
a | O_WRONLY 或 O_CREAT 或 O_APPEND |
a+ | O_RDWR或 O_CREAT 或 O_APPEND |
文件权限:
- umask:用来设定文件或目录的初始权限
- 文件或目录的初始权限 = 文件或目录的最大默认权限 - umask值
对文件来讲,其可拥有的最大默认权限是 666,即 rw-rw-rw-
对目录来讲,其可拥有的最大默认权限是 777,即 rwxrwxrwx
代码验证:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
int fd = -1;
fd = open("test.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
if(fd < 0){
printf("open file err\n");
return 0;
}
printf("open file success\n");
return 0;
}
可以看到,文件打开成功,并且文件的权限为rw-rw-r–,也就是110110100,即664,我们设置的mode为666,查看当前用户的umask值:0002,则文件的实际权限为mode-umask=666-002=664
3.文件IO文件的关闭
文件IO----close
close函数用来关闭一个打开的文件:
#include <unistd.h>
int close(int fd);
成功时返回0,出错返回EOF
程序结束时,自动关闭所有打开的文件
文件关闭后,文件描述符不在代表文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
int fd = -1;
fd = open("test.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
if(fd < 0){
printf("open file err\n");
return 0;
}
printf("open file success,fd = %d\n",fd);
int ret = close(fd);
if(ret < 0){
printf("close failed\n");
}
fd = -1;
return 0;
}
4.文件IO的读写定位
文件IO—read
read函数用来从文件中读取数据
#include <unistd.h>
ssize_t read(int fd,viod * buff,size_t count);
成功返回实际读取的字节数,出错返回EOF
读到文件末尾时,返回0
buff是接收数据的缓存区
count,要读的数据量,不应超过buf大小
文件IO—write
write函数用来向文件写入数据
#include <unistd.h>
ssize_t write(int fd,void * buff,size_t count);
成功返回实际写入的字节数,出错返回EOF
buff是发送数据的缓存区
count,要写的数据量,不应超过buf大小
文件IO—lseek
#include <unistd.h>
off_t lseek(int fd,off_t offset,int whence);
成功时返回当前文件读写位置,出错时返回EOF
offset:偏移量,可正可负
whence:SEEK_SET/SEEK_CUR/SEEK_END
SEEK_SET:从距离文件开头offset位移量为新的读写位置
SEEK_CUR:以目前的位置往后增加offset位移量为新的读写位置
SEEK_END:从距离文件末尾开始offset位移量为新的读写位置
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char* argv[])
{
int fd = -1;
int ret = 0;
char buf[32] = "Hello world";
char buf2[32] = {0};
fd = open("test.txt",O_RDWR|O_CREAT|O_APPEND,0666);
if(fd < 0){
printf("open file err\n");
return 0;
}
printf("open file success,fd = %d\n",fd);
ret = write(fd,buf,strlen(buf));
if(ret < 0){
perror("Write");
goto END;
}
printf("write count = %d\n",ret);
lseek(fd,0,SEEK_SET);
ret = read(fd,buf2,32);
if(ret < 0){
perror("read");
goto END;
}
printf("read count = %d,%s\n",ret,buf2);
END:
ret = close(fd);
if(ret < 0){
printf("close failed\n");
}
fd = -1;
printf("close success\n");
return 0;
}