函数原型:int fseek(FILE *stream, long offset, int whence);
功能:修改文件光标位置
参数1:要修改光标的文件
参数2:偏移量
>0:表示向后偏移
=0:不偏移
<0:表示向前偏移
参数3:偏移的起始位置
SEEK_SET:文件的开头
SEEK_CUR:当前位置
SEEK END:文件结尾
返回值:成功返回,失败返回-1并置位错误码
=============================================================
int main(int argc, char const *argv[])
{
FILE* fp1 = NULL;
if((fp1=fopen("./file01.txt","w+")) == NULL)
{//打开文件写数据
perror("open file");
return -1;
}
fprintf(fp1,"1: hello word\r\n");//写入一行,光标向后偏移
fprintf(fp1,"2: hello word\r\n");//写入一行,光标向后偏移
fprintf(fp1,"3: hello word\r\n");//写入一行,光标向后偏移
fprintf(fp1,"4: hello word\r\n");//写入一行,光标向后偏移
fseek(fp1,0,SEEK_SET);//光标定位到文件开头,不偏移
fgets(str1,sizeof(str1),fp1);
fclose(fp1);
printf("%s\r\n",str1);
return 0;
}
以'a'或'a+'的形式打开的文件不能更改光标位置
但是以'a+'的形式打开的文件能够修改读光标
函数原型:long ftel(FILE *stream);
功能:获取光标当前位置
参数1:文件指针
返回值:返回光标所在位置
============================================
int main(int argc, char const *argv[])
{
FILE* fp1 = NULL;
if((fp1=fopen("./file01.txt","w+")) == NULL)
{//打开文件写数据
perror("open file");
return -1;
}
fprintf(fp1,"1: hello word\r\n");//写入一行,光标向后偏移
fprintf(fp1,"2: hello word\r\n");//写入一行,光标向后偏移
fprintf(fp1,"3: hello word\r\n");//写入一行,光标向后偏移
fprintf(fp1,"4: hello word\r\n");//写入一行,光标向后偏移
printf("当前光标位置为:%ld\r\n",ftell(fp1));
fclose(fp1);
printf("%s\r\n",str1);
return 0;
}
函数原型:void rewind(FILE *stream);
功能:将文件指针回到文件的开头。
参数1:指定文件指针
返回值:无返回值
需要使用的库
#include
#include
#include
#include
文件IO:基于系统调用得方式,只要调用文件IO得接口,程序就会从用户空间向内核空间进行一次交互
效率相较于标准IO较低,因为没有缓冲区
文件IO的接口
open、read、write、close、Iseek…
文件描述符:
- 文件描述符是一个大于等于0的非负整数,使用open打开一个文件后,就会返回该文件的描述符,在之后想要操作文件,只需通过该文件描述符即可
- 在一个正在执行的程序中,默认打开了三个文件描述符0(stdin)、1(stdout)、2(stderr)
- 文件描述符的使用原则: 最小末分配原则
- 一个程序中的文件描述符的最大承载量默认为1024
int main(int argc, char const *argv[])
{
printf("fileno of stdin = %d\n", stdin->_fileno);
printf("fileno of stdout = %d\n", stdout->_fileno);
printf("fileno of stderr = %d\n", stderr->_fileno);
return 0;
}
输出>>
fileno of stdin = 0
fileno of stdout = 1
fileno of stderr = 2
int open(const char *pathname, int flags);//无需创建文件
int open(const char *pathname, int flags, mode t mode);//需要创建文件
功能:打开一个文件
参数1: 文件路径,跟fopen的第一个参数一致
参数2:打开方式
1: O_RDONLY 只读 2: O_WRONLY 只写 3: O_RDWR 读写
===============以上一个必须选择其中一个,下面的可以作为选加====================
1. O_CREAT:如果文件不存在,创建一个文件,如果加了该选项,那么第三个参数也必须要加
2. O_APPEND: 追加写
3. O_TRUNC:如果文件存在,则清空内容
4. O_EXCL: 判断文件是否已经存在,如果已经存在了,则open函数会置位错误码为: EEXIST,跟0 CREAT
5. 使用例子"w+"-> O_RDWR|O_CREAT|O_TRUNC
参数3: 掩码 文件权限,创建文件时的权限
目录的最大权限:0777
普通文件的最大权限是:0666
最终的权限是给定的(mode & rumask)
umask:是系统给定的黑认的掩码
更改掩码的指令:umask 数字
返回值:成功返回打开文件的文件描述符,失败返回-1
=========================================================================================
int main(int argc, char const *argv[])
{
int fb = 0;
if((fb=open("01open.txt",O_RDWR|O_CREAT|O_TRUNC,0777) == -1))
{//文件打开失败
perror("open file: ");
return 1;
}
close(fb);//关闭文件
return 0;
}
=========================================================================================
int main(int argc, char const *argv[])
{
int fb = 0;
if((fb=open("02open.txt",O_RDWR|O_CREAT|O_EXCL) == -1))
{//文件打开失败
if(errno == EEXIST)
{
printf("文件已存在,无需重新创建\r\n");
fb = open("02open.txt",Rp);
}else
{
perror("open file");return -1;
}
return 1;
}
close(fb);//
return 0;
}
使用宏:
#define R O_RDONLY #define W O_WRONLY|O_CREAT|O_TRUNC #define A O_WRONLY|O_CREAT|O_ACCMODE #define Rp O_RDWR #define Wp O_RDWR|O_CREAT|O_TRUNC #define Ap O_RDWR|O_CREAT|O_TRUNC
umask是创建文件时的掩码,默认为0002,对其他用户没有写功能
查看umask
修改umask
头文件:
#include
函数原型:int close(int fd);
功能:关闭一个文件参数:要关闭文件的文件描述符
返回值: 成功返回e,失败返回-1并置位错误码
===========================================
close(1);
函数原型:ssize_t read(int fd, void *buf, size_t count);
功能:从给定文件中读取从count个数据到buf中
参数1:被读取文件
参数2:读取后的数据容器,是一个万能指针,可以读取任意类型的数据
参数3:读取的数量
返回值:返回值>0读取的个数,返回值=0文件读取结束,失败返回-1并置位错误码
函数原型:ssize_t write(int fd, const void *buf, size_t count);
功能:向给定文件中写入buf中的count个数据到fdq中
参数1:被写文件
参数2:读取后的数据容器,是一个万能指针,可以读取任意类型的数据
参数3:读取的数量
返回值:返回值>0读取的个数,返回值=0文件读取结束,失败返回-1并置位错误码
函数原型:off_t lseek(int fd, off_t offset, int whence);
功能:移动光标位置
参数1:文件描述符
参数2:偏移量
参数3:偏移的起始位置
1. SEEK_SET:文件开头
2. SEEK_CUR:当前位置
3. SEEK_END:文件末尾
返回值:失败返回-1,并置位错误码,超过返回光标当前位置到文件开头的偏移量
使用变量拷贝文件描述符,其实
只是拷贝变量的值
,并没有产生新的文件描述符,只是在程序中多了一个变量,记录该文件描述符而已,所以无论操作哪个变量,都是对该文件描述符的操作,使用的是同一个光标
#include
int main(int argc, const char *argv[])
{
int fd1;
//以只读的形式打开一个文件
if((fd1 = open("./open.txt", O_RDONLY)) == -1)
{
perror("open file");
return -1;
}
//定义容器
char buf[10] = "";
int ret = read(fd1, buf, sizeof(buf));
write(1, buf, ret); //向终端打印数据
printf("\n");
int fd2 = fd1; //将文件描述符直接拷贝
printf("fd1 = %d, fd2 = %d\n", fd1, fd2);
char buf1[10];
ret = read(fd2, buf1, sizeof(buf1));
write(1, buf1, ret);//如果终端上输出的跟fd1输出结果一致
//说明两个文件使用的是不同光标
//如果不一致,说明两个文件使用的是同一光标
return 0;
}
文件原型:int dup(int oldfd);
功能:通过给定的旧文件描述符,拷贝出一个新文件描述符
参数:旧文件描述符
返回值:成功返回:新文件描述符,使用最小未使用原则
失败返回-1并置位错误码
===================================================================
int main(int argc, char const *argv[])
{
int fd1 = 0;
int fd2 = 0;
int ret = 0;
char str[5] = {0};
if((fd1 = open("./file01.txt",R)) == -1)
{//文件打开失败
perror("open file");
return -1;
}
fd2 = dup(fd1);//拷贝出一个新的文件描述符,其大小为最小的未使用的描述符
printf("fd1 = %d fd2: %d \r\n",fd1,fd2);
close(fd1);
close(fd2);
return 0;
}
输出>>
fd1 = 3 fd2: 4
两个文件描述符不共享光标
int main(int argc, char const *argv[])
{
int fd1 = 0;
int fd2 = 0;
int ret = 0;
char str[5] = {0};
if((fd1 = open("./file01.txt",R)) == -1)
{//文件打开失败
perror("open file");
return -1;
}
if((fd2 = open("./file01.txt",R)) == -1)
{//文件打开失败
perror("open file");
return -1;
}
printf("fd1 = %d fd2: %d \r\n",fd1,fd2);
close(fd1);
close(fd2);
return 0;
}
输出>>
fd1 = 3 fd2: 4
函数原型:int dup2(int oldfd, int newfd);
函数功能:它将文件描述符oldfd复制到文件描述符newfd上,如果newfd已经打开,则先将其关闭。
dup2返回的是复制后的文件描述符newfd
参数1:旧的文件描述符
参数2:新的文件描述符
返回值:如果出现错误则返回-1。
=======================================================================
dup2(fd, STDIN_FILENO); // 将fd重定向到标准输入
dup2(fd, STDOUT_FILENO); // 将fd重定向到标准输出
dup2(fd, STDERR_FILENO); // 将fd重定向到标准错误
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
int fd1 = 0;
int fd2 = 0;
int ret = 0;
char str[50] = {0};
char file_path[100] = {0};
if((fd1 = open("./file01.txt",R)) == -1)
{//文件打开失败
perror("open file");
return -1;
}
snprintf(str,sizeof(str), "/proc/self/fd/%d", fd1);
readlink(str,file_path,sizeof(file_path)-1);
printf("%s\n",file_path);
close(fd1);
close(fd2);
return 0;
}
输出>>
/home/ubuntu/Desktop/learn/IO/5_26/file01.txt
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define R O_RDONLY
#define W O_WRONLY|O_CREAT|O_TRUNC
#define A O_WRONLY|O_CREAT|O_ACCMODE
#define Rp O_RDWR
#define Wp O_RDWR|O_CREAT|O_TRUNC
#define Ap O_RDWR|O_CREAT|O_TRUNC
int main(int argc, char const *argv[])
{
int fd1 = 0;
int fd2 = 0;
int ret = 0;
int cnt = 0;
char str[5] = {0};
if((fd1 = open("./file01.txt",R)) == -1)
{//文件打开失败
perror("open file");
return -1;
}
if((fd2 = open("./file02.txt",W,0666)) == -1)
{//文件打开失败
perror("open file");
return -1;
}
do
{
ret = read(fd1,str,sizeof(str));
cnt+=ret;
write(fd2,str,ret);
}while(ret);
printf("文件大小: %d\n",cnt);
close(fd1);
close(fd2);
return 0;
}