创建文件操作的头文件
这个类设计的目的是提供一个简单而全面的接口,以便进行常见的大文件操作。它封装了文件的打开、关闭、读写等基本操作,使得在应用程序中更容易使用和维护。
file_op.h
#ifndef AIRWAVE_LARGE_FILE_OP_H_
#define AIRWAVE_LARGE_FILE_OP_H_
#include"common.h"
namespace Airwave
{
namespace largefile
{
class FileOperation
{
public:
FileOperation(const std::string& file_name, const int open_flags = O_RDWR | O_LARGEFILE);
~FileOperation();
int open_file();
int close_file();
int flush_file(); //把文件立即写入磁盘
int unlink_file(); //删除文件
int pread_file(char* buf, const int32_t nbytes, const int64_t offset); //从文件中读取数据
int pwrite_file(const char* buf, const int32_t nbytes, const int64_t offset); //向文件中写入数据
int write_file(const char* buf,const int32_t nbytes); //向文件中写入数据
int64_t get_file_size(); //获取文件大小
int ftruncate_file(const int64_t length);
int seek_file(consst int64_t open_file);
int get_fd() const { return fd_ };
protected:
int fd_;
int open_flags_; //打开文件的方式
char* file_name_; //文件名
protected:
static const mode_t OPEM_MODE = 0644; //文件权限
static const int MAX_DISK_TIMES = 5; //最大磁盘读取次数
};
}
}
#endif // !Airwave_LARGE_FILE_OP_H_
文件操作函数:
open_file
: 打开文件close_file
: 关闭文件flush_file
: 立即将文件写入磁盘unlink_file
: 删除文件pread_file
: 从文件中指定偏移位置读取数据pwrite_file
: 在文件的指定偏移位置写入数据write_file
: 在文件末尾写入数据get_file_size
: 获取文件大小ftruncate_file
: 截断文件至指定长度seek_file
: 移动文件指针
fd_
: 文件描述符。open_flags_
: 打开文件的方式。file_name_
: 文件名。
check_file
: 检查文件是否打开,如果没有打开则打开文件。
OPEN_MODE
: 文件权限,默认为 0644。MAX_DISK_TIMES
: 最大磁盘读取次数。
file_op.cpp
#include"file_op.h"
#include"common.h"
namespace Airwave
{
namespace largefile
{
FileOperation::FileOperation(const std::string& filename, const int open_flags)
:fd_(-1),open_flags_(open_flags)
{
file_name_ = strdup(filename.c_str());
//strdup()函数将字符串复制到一个新的内存空间中,返回指向这块内存的指针
}
FileOperation::~FileOperation()
{
if (fd_ >0)
{
::close(fd_);
}
if (file_name_ != NULL)
{
free(file_name_);
}
}
//打开文件
int FileOperation::open_file()
{
if (fd_ > 0) //如果打开失败,关闭文件,并将文件描述符置为-1
{
close(fd_);
fd_ = -1;
}
fd_ = ::open(file_name_, open_flags_, OPEM_MODE); //参数为:文件名,文件打开方式,文件权限
if (fd_ < 0)
{
return -errno; //打开失败返回错误码
}
return fd_; //打开成功返回fd
}
//关闭文件
void FileOperation::close_file()
{
if (fd_ < 0)
{
return;
}
::close(fd_);
fd_ = -1;
}
int FileOperation::pread_file(char* buf, const int32_t nbytes, const int64_t offset)
{
int32_t left = nbytes; //剩余的字节数
int64_t read_offset = offset; //读取的偏移量
int32_t read_len = 0; //读取的长度
char* p_tmp = buf; //指向buf的指针
int i = 0;
while(left>0)
{
++i;
if(i>=MAX_DISK_TIMES)
{
break;
}
if(check_file()<0)
{
return -errno;
}
read_len = ::pread64(fd_,p_tmp,left,read_offset); //从文件中读取数据
if(read_len<0) //如果读取失败
{
read_len = -errno;
if(-read_len == EINTR || -read_len == EAGAIN) //如果是中断或者是阻塞,则继续读取
{
continue;
}
else if(-read_len == EBADF) //如果是文件描述符无效,则将fd_置为-1
{
fd_ = -1;
continue;
}
else{
return read_len;
}
}
else if(read_len == 0) //如果读取到文件末尾
{
break;
}
left -= read_len; //更新剩余字节数
read_offset += read_len; //更新读取偏移量
p_tmp += read_len; //更新指针
}
if(left != 0)
{
return EIXT_DISK_OPER_INCOMPLETE; //如果读取的字节数不等于要求的字节数,则返回错误码
}
return TFS_SUCCESS;
}
int FileOperation::pwrite_file(const char* buf, const int32_t nbytes, const int64_t offset)
{
int32_t left = nbytes; //剩余的字节数
int64_t write_offset = offset; //写入的偏移量
int32_t written_len = 0; //写入的长度
const char* p_tmp = buf; //指向buf的指针
int i = 0;
while(left>0)
{
++i;
if(i>=MAX_DISK_TIMES)
{
break;
}
if(check_file()<0)
{
return -errno;
}
written_len = ::pwrite64(fd_,p_tmp,left,write_offset); //从文件中读取数据
if(written_len<0) //如果读取失败
{
written_len = -errno;
if(-written_len == EINTR || -written_len == EAGAIN) //如果是中断或者是阻塞,则继续读取
{
continue;
}
else if(-written_len == EBADF) //如果是文件描述符无效,则将fd_置为-1
{
fd_ = -1;
continue;
}
else{
return written_len;
}
}
left -= written_len; //更新剩余字节数
write_offset += written_len; //更新读取偏移量
p_tmp += written_len; //更新指针
}
if(left != 0)
{
return EIXT_DISK_OPER_INCOMPLETE; //如果读取的字节数不等于要求的字节数,则返回错误码
}
return TFS_SUCCESS;
}
int FileOperation::write_file(const char* buf,const int32_t nbytes)
{
int32_t left = nbytes; //剩余的字节数
int32_t written_len = 0; //写入的长度
const char* p_tmp = buf; //指向buf的指针
int i = 0;
while(left>0)
{
++i;
if(i>=MAX_DISK_TIMES)
{
break;
}
if(check_file()<0)
{
return -errno;
}
written_len = ::write(fd_,p_tmp,left); //从文件中读取数据
if(written_len<0) //如果读取失败
{
written_len = -errno;
if(-written_len == EINTR || -written_len == EAGAIN) //如果是中断或者是阻塞,则继续读取
{
continue;
}
else if(-written_len == EBADF) //如果是文件描述符无效,则将fd_置为-1
{
fd_ = -1;
continue;
}
else{
return written_len;
}
}
left -= written_len; //更新剩余字节数
p_tmp += written_len; //更新指针
}
if(left != 0)
{
return EIXT_DISK_OPER_INCOMPLETE; //如果读取的字节数不等于要求的字节数,则返回错误码
}
return TFS_SUCCESS;
}
//获取文件大小,不一定需要打开文件,也可以直接通过文件名获取文件大小
int64_t FileOperation::get_file_size()
{
int fd = check_file();
if (fd < 0)
{
return -1;
}
struct stat buf;
if(fstat(fd,&buf) != 0)
{
return -1;
}
else
{
return buf.st_size;
}
}
int FileOperation::check_file()
{
if(fd_ < 0)
{
fd_ = open_file();
}
return fd_;
}
//改变文件大小
int FileOperation::ftruncate_file(const int64_t length)
{
int fd = check_file();
if (fd < 0)
{
return fd;
}
return ::ftruncate(fd,length); //截断到指定长度,可以增长也可以缩短
}
//移动文件读写位置
int FileOperation::seek_file(const int64_t offset)
{
int fd = check_file();
if(fd < 0)
{
return fd;
}
return lseek(fd,offset,SEEK_SET); //SEEK_SET表示从文件头开始偏移,offset表示偏移量
}
//同步文件数据
int FileOperation::flush_file()
{
if(open_flags_ & O_SYNC) //如果打开文件时指定了O_SYNC标志,则不需要调用fsync
{
return 0;
}
int fd = check_file();
if (fd < 0)
{
return fd;
}
return fsync(fd); //将缓冲区的数据写入磁盘
}
//删除文件
int FileOperation::unlink_file()
{
close_file();
return ::unlink(file_name_);
}
}
}
file_op_test.cpp
#include"file_op.h"
#include"common.h"
using namespace std;
using namespace Airwave;
int main(void)
{
const char* filename = "file_op.txt";
largefile::FileOperation* fileOP = new largefile::FileOperation(filename, O_RDWR | O_CREAT | O_LARGEFILE);
int fd = fileOP->open_file(); //打开文件
if (fd < 0)
{
fprintf(stderr, "open file %s failed. reason : %s\n",filename, strerror(-fd));
exit(-1);
}
char buffer[65];
//第一次写入
memset(buffer, 'a', 64);
int ret = fileOP->pwrite_file(buffer, 64, 128);
if (ret < 0)
{
if(ret == largefile::EIXT_DISK_OPER_INCOMPLETE)
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
else
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
}
else
{
printf("write file %s success.\n",filename);
}
//第一次读取
memset(buffer, 0, 64);
ret = fileOP->pread_file(buffer, 64, 128);
if (ret < 0)
{
if(ret == largefile::EIXT_DISK_OPER_INCOMPLETE)
{
fprintf(stderr, "read file %s failed. reason : %s\n",filename, strerror(-ret));
}
else
{
fprintf(stderr, "read file %s failed. reason : %s\n",filename, strerror(-ret));
}
}
else
{
buffer[64] = '\0';
printf("read file %s success. content : %s\n",filename, buffer);
}
//第二次写入
memset(buffer, 'b', 64);
ret = fileOP->write_file(buffer, 64);
if (ret < 0)
{
if(ret == largefile::EIXT_DISK_OPER_INCOMPLETE)
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
else
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
}
else
{
printf("write file %s success.\n",filename);
}
//第二次读取
memset(buffer, 0, 64);
ret = fileOP->pread_file(buffer, 64, 0);
if (ret < 0)
{
if(ret ==largefile::EIXT_DISK_OPER_INCOMPLETE)
{
fprintf(stderr, "read file %s failed. reason : %s\n",filename, strerror(-ret));
}
else
{
fprintf(stderr, "read file %s failed. reason : %s\n",filename, strerror(-ret));
}
}
else
{
buffer[64] = '\0';
printf("read file %s success. content : %s\n",filename, buffer);
}
//文件指针并不移动,第二次写入的时候会写在第一次前面的数据上
char buffer2[256];
memset(buffer2, 'c', 256);
ret = fileOP->write_file(buffer2, 256);
if (ret < 0)
{
if(ret == largefile::EIXT_DISK_OPER_INCOMPLETE)
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
else
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
}
else
{
printf("write file %s success.\n",filename);
}
memset(buffer, 'd', 256);
ret = fileOP->write_file(buffer, 256);
if (ret < 0)
{
if(ret == largefile::EIXT_DISK_OPER_INCOMPLETE)
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
else
{
fprintf(stderr, "write file %s failed. reason : %s\n",filename, strerror(-ret));
}
}
else
{
printf("write file %s success.\n",filename);
}
fileOP->close_file();
}