文件IO
目录
文件IO
- 文件IO没有缓存
一、什么是文件IO?
前面我们介绍过文件IO又叫做系统调用,它遵从POSIX标准。它是不带缓存的和操作系统
相交互的接口函数。常用的接口如下:。如果要学习文件IO首先必须理解文件描述符。
include <unistd.h> //系统调用的头文件
二、什么是文件描述符?
- 对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,用open返回的文件描述符标识该文件,将其作为参数传送给read或write。
- 注:在一个进程能默认可以打开的文件的个数是1024个,所以文件描述符的范围【0-1023】。但是用户也可以通过 ulimit -n 2048将打开的文件描述符的值修改为2048个通过ulimit -a查看修改后的信息。
- 0 代表标准输入,PC环境下对应一般是键盘
- 1 代表标准输出,PC环境下对应一般是显卡管理的显示器
- 2 代表错误输出
[1] 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);
-
功能:按照用户设置的方式打开文件
-
参数:
- pathname :文件的名(绝对或者相对路径)
- flags:打开文件的方式
- O_RDONLY 只读
- O_WRONLY 只写
- O_RDWR 读写
- O_APPEND 追加
- O_CREAT 新建文件
- O_TRUNC 清空
- O_NONBLOCK - 非阻塞
- mode:当指定O_CREAT,这表示创建文件的文件权限,如果为指定则忽略这个参数
-
返回值:成功返回文件描述符,失败返回-1,同时置位errno
[2] umask 掩码
注:创建文件的实际的权限是和umask有关系的
- 假如掩码为 002 这是一个八进制数,如果你用open的creat来设置文件权限为 0666,那么文件真正的权限是(0666 & ~(0002)),相当于掩盖了其他人的可写权限
- umask 022可以修改掩码的值
[2] close 关闭文件
- 头文件:
#include <unistd.h> - 函数原型:
int close(int fd); - 功能:关闭文件
- 参数:@fd:文件描述符
- 返回值:成功返回0,失败返回-1,同时置位errno
[3] 标准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
[4] read
- 头文件:
#include <unistd.h> - 函数原型:
ssize_t read(int fd, void *buf, size_t count); - 功能:将文件中的数据读取到buf中
- 参数:
- fd:文件描述符
- buf:缓冲区
- count:读取的字节的个数,如果返回0表示文件已经读取完
- 返回值:成功返回读取到的字节的个数,失败返回-1并设置errno
[5] write
- 头文件:
#include <unistd.h> - 函数原型:
ssize_t write(int fd, const void *buf, size_t count); - 功能:将buf中的数据写入到文件
- 参数:
- fd:文件描述符
- buf:缓冲区
- count:读取的字节的个数
- 返回值:成功返回读取到的字节的个数,失败返回-1并设置errno
[6] lseek
- 头文件:
#include <sys/types.h>#include <unistd.h>
- 函数原型:
off_t lseek(int fd, off_t offset, int whence); - 功能: 移动文件指针
- 参数:
- fd 文件描述符
- offset 偏移值
- whence:
- SEEK_SET: 文件开头位置
- SEEK_CUR: 当前文件指针位置
- SEEK_END: 文件结尾位置
- 返回值: 成功返回设置后的文件指针相对于文件开始的偏移值,失败返回 -1设置errno
[7] 练习:使用系统调用完成文件的拷贝?
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
if(argc != 3) {
printf("usage: ./a.out src dist\n");
return -1;
}
// argv[1] 源文件
// argv[2] 目标文件
int fd_src = open(argv[1], O_RDONLY);
if(fd_src == -1) {
perror("open");
return fd_src;
// return -1;
}
int fd_dist = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0664);
if(fd_dist == -1) {
perror("open");
close(fd_src);
return fd_src;
}
char buf[100] = {0};
while(1) {
int ret = read(fd_src, buf, 100);
if(ret == 0) { // 如果 read 的返回值为 0 表示读到文件结尾
printf("read end of file\n");
break;// 跳出循环
}
// ret 的值是 读到了多少字节数据
write(fd_dist, buf, ret);
}
// 关闭文件
close(fd_src);
close(fd_dist);
return 0;
}
[8] 重定向
-
头文件:
#include <stdio.h> -
函数原型:
FILE *freopen(const char *path, const char *mode, FILE *stream); -
功能:重定向【把打开的文件描述符定向到新的文件】
-
参数:
- const char *path - 指向带路径的文件名
- const char *mode - 指向操作方式字符串,如下仅能选择其中一个
- "r":文件存在,且只读打开,文件位置在开头
- "r+":文件存在,读写打开,文件位置在开头
- "w":文件存在清空文件内容只写打开,文件不存在创建文件只写打开,文件位置在开头
- "w+":文件存在清空文件内容读写打开,文件不存在创建文件读写打开,文件位置在开头
- "a":文件存在则从文件尾巴开始写【定位位置在文件尾】打开,文件不存在创建文件只写打开,文件位置在文件尾
- "a+":文件存在则从文件尾巴开始读写【定位位置在文件尾】打开,文件不存在创建文件读写打开,文件位置在文件尾
- FILE *stream: 文件指针
-
实例
#include <stdio.h> int main() { //把标准输出定向到1.txt FILE *fp = freopen("1.txt", "w+", stdout); if(NULL == fp){ perror("freopen"); return 0; } //其实际内部是调用标准输出,向终端输出格式化字符串 printf("hello world\n"); //关闭重定向 fclose(fp); }
【9】opendir/readdir/closedir
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录
参数:
@name:目录的名字
返回值:成功返回目录的流指针,失败返回NULL,并设置errno
struct dirent *readdir(DIR *dirp);
功能:读取目录下的文件
参数:
@dirp:打开目录返回的目录的流指针
返回值:成功返回struct dirent的结构体指针
失败或者读取到结尾返回NULL,如果读取到结尾不会置位errno,如果失败会设置errno
struct dirent {
ino_t d_ino; //文件的inode号
off_t d_off; //在目录中的偏移
unsigned short d_reclen; //文件名的长度
unsigned char d_type; //文件的类型
char d_name[256]; //保存文件名的数组
};
int closedir(DIR *dirp);
功能:关闭目录流指针
参数:
@dirp:目录流指针
返回值:成功返回0,失败返回-1并设置errno
-
示例代码
// 获取当前目录下的文件名,并打印出来 #include <stdio.h> #include <sys/types.h> #include <dirent.h> int main(int argc, const char *argv[]) { DIR * dir; if (NULL == (dir = opendir("./"))) { perror("opendir error "); return -1; } struct dirent * d = NULL; puts("\n***********************************************"); while (d = readdir(dir)) printf("filename: %s\n", d->d_name); putchar('\n'); return 0; }

浙公网安备 33010602011771号