目录
1. 文件IO的概念
2. 文件描述符概念
3. 函数介绍
3.1 文件IO-open函数
3.2 文件IO-close函数
3.3 文件IO-read函数
3.4 文件IO-write函数
3.5 文件IO-lseek函数
4. 代码练习
4.1 要求
4.2 具体实现代码
4.3 测试结果
5. 总结
1. 文件IO的概念
posix(可移植操作系统接口)定义的一组函数;
不提供缓冲机制,每次读写操作都引起系统调用;
核心概念是文件描述符;
访问各种类型文件;
Linux下, 标准IO基于文件IO实现;
注意:文件IO不提供缓冲机制。
文件IO与标准IO的对比如下表:
标准IO | 文件IO | |
打开 | fopen,freopen,fdopen | open |
关闭 | fclose | close |
读 | getc,fgetc,getchar,fgets,gets,fread | read |
写 | putc,fputc,putchar,fputs,puts,fwrite | write |
2. 文件描述符概念
- 每个打开的文件都对应一个文件描述符。
- 文件描述符是一个非负整数。Linux为程序中每个打开的文件分配一个文件描述符。
- 文件描述符从0开始分配,依次递增。
- 文件IO操作通过文件描述符来完成。
3. 函数介绍
3.1 文件IO-open函数
open函数用来创建或打开一个文件
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
- 成功时返回文件描述符;出错时返回EOF
- 打开文件时使用两个参数
- 创建文件时第三个参数指定新文件的权限,(只有在建立新文件时有效)此外真正建文件时的权限会受到umask 值影响,实际权限是mode-umaks
- 可以打开设备文件,但是不能创建设备文件
- umask :用来设定文件或目录的初始权限
- 文件和目录的真正初始权限
- 文件或目录的初始权限 = 文件或目录的最大默认权限 - umask权限
原型 | int open(const char *pathname,int flags,mode_t mode); | ||
参数 | pathname | 被打开的文件名(可包括路径名) | |
flags | O_RDONLY:只读方式打开 | 这三个参数互斥 | |
O_WRONLY:只写方式打开 | |||
O_RDWR:读写方式打开 | |||
O_CREAT:如果该文件不存在,就创建一个新的文件,并用第三个参数为其设置权限。 | |||
O_EXCL:如果使用O_CREAT时文件存在,则可返回错误信息,这一参数可测试文件是否存在。 | |||
O_NOCTTY:使用本参数时,如文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制终端。 | |||
O_TRUNC:如文件已经存在,那么打开文件时先删除文件中原有数据。 | |||
O_APPEND:以添加方式打开文件,所以对文件的写操作都在文件的末尾进行。 | |||
mode | 被打开文件的存取权限,为8进制表示法。 |
标准IO与文件IO 文件打开方式参数对照如下:
r | O_RDONLY |
r+ | O_RDWR |
w | O_WRONLY | O_CREAT | O_TRUNC, 0664 |
w+ |
O_RDWR | O_CREAT | O_TRUNC, 0664
|
a | O_WRONLY | O_CREAT | O_APPEND, 0664 |
a+ | O_RDWR | O_CREAT | O_APPEND, 0664 |
3.2 文件IO-close函数
close函数用来关闭一个打开的文件:
#include <unistd.h>
int close(int fd);
- 成功时返回0;出错时返回EOF
- 程序结束时自动关闭所有打开的文件
- 文件关闭后,文件描述符不再代表文件
3.3 文件IO-read函数
read函数用来从文件中读取数据:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
- 成功时返回实际读取的字节数;出错时返回EOF
- 读到文件末尾时返回0
- buf是接收数据的缓冲区
- count不应超过buf大小
3.4 文件IO-write函数
write函数用来向文件写入数据:
#include <unistd.h>
ssize_t write(int fd, void *buf, size_t count);
- 成功时返回实际写入的字节数;出错时返回EOF
- buf是发送数据的缓冲区
- count不应超过buf大小
3.5 文件IO-lseek函数
lseek函数用来定位文件:
#include <unistd.h>
off_t lseek(int fd, off_t offset, intt whence);
- 成功时返回当前的文件读写位置;出错时返回EOF
- 参数offset和参数whence同fseek完全一样
4. 代码练习
4.1 要求
1、每隔1s以指定格式 “年-月-日” 分别写入文件和缓冲区;
2、该程序无限循环,直到Ctrl+C中断程序;
4.2 具体实现代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
int main(int argc,char*argv[])
{
int fd;
int ret;
int linecount = 0;
time_t ctime;
struct tm* ctimester;
fd = open("1.txt",O_RDWR|O_CREAT|O_APPEND,0666);
if(fd<0)
{
printf("open file failed\n");
return 0;
}
while(1)
{
ctime = time(NULL);
ctimester = localtime(&ctime);//Get Time
char str[32];//Write String
printf("%04d-%02d-%02d %02d:%02d:%02d\n",ctimester->tm_year+1900,
ctimester->tm_mon+1,
ctimester->tm_mday,
ctimester->tm_hour,
ctimester->tm_min,
ctimester->tm_sec);
sprintf(str,"%d, %04d-%02d-%02d %02d:%02d:%02d\n",linecount++,ctimester->tm_year+1900,
ctimester->tm_mon+1,
ctimester->tm_mday,
ctimester->tm_hour,
ctimester->tm_min,
ctimester->tm_sec);
ret = write(fd,str,strlen(str));
if(ret<0)
{
perror("write");
goto END;
}
lseek(fd,0,SEEK_SET);
sleep(1);
}
END:
close(fd);
return 0;
}
4.3 测试结果
5. 总结
本文总结了Linux下文件IO的打开、关闭、读写、定位函数介绍,并根据这些函数进行了一个包含文件打开关闭、读写、格式化输出等内容的实现。