前言
文件I/O又称为低级磁盘I/O,遵循POSIX相关标准。在Linux系统中所有的I/O 操作是通过读文件以及写文件的方式来完成的。通过文件I/O读写文件时,每次操作都会执行相关系统调用。这样处理文件的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销。文件I/O中用文件描述符表示一个打开的文件,可以访问不同类型的文件,如普通文件、设备文件和管道文件等。
文件描述符
文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程打开文件的记录表。通常,一个进程启动时,都会打开3个流:标准输入、标准输出和标准出错。这3个流分别对应文件描述符0、1和2(对应的宏分别是STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO)
文件I/O相关函数
操作文件的步骤:
打开文件
操作文件(读/写)
关闭文件
1.打开文件(open()函数)
头文件: #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
1.1(两个参数)
函数原型: int open(const char *pathname, int flags);
功能:用于打开一个指定的文件
参数1:文件名(带路径)
参数2:打开的文件方式
返回值:成功返回值为非负的整数(文件描述符)
失败返回-1
1.2(三个参数)
函数原型:int open(const char *pathname, int flags, mode_t mode);
功能:用于打开一个指定的文件
参数1:文件名(带路径)
参数2:打开的文件方式
参数3:一般新建文件的时候,需要第三个参数为其设置权限
返回值:成功返回值为非负的整数(文件描述符)
失败返回-1
打开方式:
以下三种方式必须其一
O_RDONLY:以只读的方式打开文件
O_WRONLY:以只写的方式打开文件
O_RDWR:以可读可写的方式打开文件
其余的,和上面进行或运算
O_CREAT:如果文件不存在,则新建,但同时必须使用第三个参数
O_EXCL:如果文件存在则出错
O_NOCTTY: 使用本参数时,若文件为终端,那么该终端不可以作为调用open()系统调用的那个进程的控制终端。
O_TRUNC:如文件已经存在,那么打开文件时先删除文件中原有数据。
O_APPEND:以添加方式打开文件,如果文件存在则追加在文件的末尾。
2.关闭文件(close()函数)
头文件:#include <unistd.h>
函数原型:int close(int fd);
参数:open函数的返回值,已经打开的文件描述符
返回值:成功返回0,失败返回-1
例:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd;
if((fd = open("text.txt",O_RDONLY | O_WRONLY | O_CREAT,0666)) <0)
{
perror("open error");
return -1;
}
close(fd);
return 0;
}
3.操作文件(读写操作)
3.1read()函数
头文件: #include <unistd.h>
函数原型:ssize_t read(int fd, void *buf, size_t count);
功能:从指定的文件中读取内容
参数1:文件描述符
参数2:存储读取到的内容的空间首地址
参数3:指定要读的字节数
返回值:成功:读取到的字节个数(大于0)
失败:返回值为-1
等于0代表读取到文件末尾了
3.2write()函数
头文件:#include <unistd.h>
函数原型:ssize_t write(int fd, const void *buf, size_t count);
功能:给指定的文件中写入内容
参数1:文件描述符
参数2:存储需要被写入的内容所在的空间的首地址
参数3:指定要写的字节数
返回值: 成功:写入文件的的字节个数(大于0)
失败:返回值为-1
等于0代表此时未写入
例:文件的拷贝
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
//入参判断
if(argc < 3)
{
printf("please try again!\n");
return -1;
}
//打开文件
//打开要读取的文件
int fr = open(argv[1],O_RDONLY);
if(fr < 0)
{
perror("open fr error");
return -1;
}
//打开要写入的文件
int fw = open(argv[2].O_WRONLY | O_CREAT,0664);
if(fw < 0)
{
perror("open fw error");
return -1;
}
char buf[1024] = {0};
while(1)
{
int ret = read(fr,buf,sizeof(buf));
if(0 == ret)
{
break;
}
else if(ret < 0)
{
printf("读取文件失败\n");
}
write(fw,buf,sizeof(buf));
}
//关闭文件
close(fr);
close(fw);
return 0;
}
3.3其他函数
头文件:#include<sys/types.h>
#include<unistd.h>
函数原型:off_t lseek(int fd, off_t offset, int whence);
参数1:文件描述符
参数2:偏移量
参数3:偏移的位置
SEEK_SET:从文件开头
SEEK_CUR:从当前位置
SEEK_END:从文件末尾
返回值:成功返回文件当前读写位置
失败返回-1
例:空洞文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
//入参判断
if(argc < 2)
{
printf("输入有误!\n");
return -1;
}
//打开文件
int fw = open(argv[1],O_WRONLY | O_CREAT,0664);
if( fw < 0 )
{
perror("open error");
return -1;
}
//操作文件
lseek(fw,1024*1024*1024,SEEK_SET);
write(fw,"\0",1);
//关闭文件
close(fw);
return 0;
}