一、介绍
文件IO
,又称系统IO
,系统调用
是操作系统
提供的API接口函数
。
posix(可移植操作系统接口)定义的一组函数
- 不提供
缓冲机制
,每次读写操作都引起系统调用
- 核心概念是
文件描述符
- 访问
各种类型文件
- Linux下,
标准IO
基于文件IO
实现
二、文件描述符
英文:缩写
fd(file descriptor)
是0-1023
的数字
,表示文件
。
每个打开
的文件都对应一个文件描述符
。文件描述符
是一个非负整数
。Linux为程序中每个打开的文件分配一个文件描述符。- 文件描述符从
0
开始分配,依次递增
。 文件IO操作
通过文件描述符来完成。0, 1, 2
表示标准输入
,标准输出
,错误
三、文件打开与关闭
1、文件打开
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
open函数
用来创建或打开
一个文件:
成功
时返回文件描述符
;出错
时返回EOF(-1)
打开文件
时使用两个参数
创建文件
时第三个参数
指定新文件的权限
,(只有在建立新文件时有效)此外真正建文件时的权限会受到umask
值影响,实际权限
是mode-umaks
(umask 用来设定文件或目录的初始权限)- 可以打开
设备文件
,但是不能创建设备文件
参数图:
与标准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
示例:
int fd;
if ((fd = open(“1.txt”, O_RDWR|O_CREAT|O_EXCL, 0666)) < 0)
{
if (errno == EEXIST)
{
perror(“exist error”);
} else
perror(“other error”);
}
2、文件关闭
#include <unistd.h>
int close(int fd);
用法与fclose相同,函数用来
关闭一个打开的文件
:
成功
时返回0
;出错
时返回EOF(-1)
- 程序结束时
自动关闭
所有打开的文件 文件关闭
后,文件描述符
不再代表文件
四、文件读取、写入与定位
1、文件写
#include <unistd.h>
ssize_t write(int fd, void *buf, size_t count);
write函数
用来向文件写入数据
:
成功
时返回实际写入的字节数
;出错
时返回EOF(-1)
buf
是发送数据
的缓冲区
count
不应超过buf
大小
示例:将键盘输入的内容写入文件,直到输入quit
int fd;
char buf[20];
if ((fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
{
perror(“open”);
return -1;
}
while (fgets(buf, 20, stdin) != NULL)
{
if (strcmp(buf, “quit\n”) == 0)
break;
write(fd, buf, strlen(buf));
}
……
2、文件读
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
read函数
用来从文件中读取数据
:
成功
时返回实际读取的字节数
;出错
时返回EOF(-1)
- 读到文件末尾时
返回0
buf
是接收数据
的缓冲区
count
不应超过buf
大小
示例:从指定的文件(文本文件)中读取内容并统计大小
int main(int argc, char *argv[])
{
int fd, n, total = 0;
char buf[64];
if (argc < 2)
{
printf(“Usage : %s <file>\n”, argv[0]);
return -1;
}
if ((fd = open(argv[1], O_RDONLY)) < 0)
{
perror(“open”);
return -1;
}
while ((n = read(fd, buf, 64)) > 0)
{
total += n;
}
……
3、文件定位
#include <unistd.h>
off_t lseek(int fd, off_t offset, intt whence);
lseek函数
用来定位文件
:
成功
时返回当前的文件读写位置
;出错
时返回EOF(-1)
参数offset
和参数whence
同fseek
完全一样
五、使用文件IO函数写日志程序
程序在上一节已经实现过,这里主要看与标准IO编写的区别就行了。
文章链接:【Linux】应用篇三–流的刷新定位与格式化输入输出
/*
* @Author: xiuchengzhen
* @Date: 2022-03-17 10:40:17
* @LastEditTime: 2022-03-17 11:39:41
*/
#include<stdio.h>
#include<unistd.h>
#include<time.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc, const char *argv[])
{
long int clock;
struct tm *clocktim;
int order = 1;
char str[32] = {0}, buf[32] = {0};
int p = open("1.txt", O_RDWR|O_CREAT|O_APPEND, 0664);
if(p == -1)
{
perror("fopen:");
return -1;
}
while(read(p, str, 32) != 0) //读到最后一行时,没有数据返回0
{
if(str[strlen(str)] == '\0')
order++;
}
while(1)
{
clock = time(NULL);
clocktim = localtime(&clock);
sprintf(buf,"%d.%04d-%02d-%02d %02d:%02d:%02d\n", order, clocktim->tm_year+1900, clocktim->tm_mon+1,
clocktim->tm_mday,clocktim->tm_hour, clocktim->tm_min, clocktim->tm_sec); //先将数据存入buf
printf("%s", buf);
if(write(p, buf, strlen(buf)) == -1) //将buf的时间数据写入文件内
{
perror("write:");
return -1;
}
memset(buf, 0 ,sizeof(buf));
order++;
sleep(1);
}
close(p);
return 0;
}
到这里就结束啦!