文件操作的封装

1 文件操作的封装

为了更加方便对文件进行操作,我们这里对系统提供的API进行封装。主要实现在file_op.h和file_op.cpp中。

1.1 代码实现

file_op.h:

#ifndef QINIU_LARGE_FILE_OP_H_
#define QINIU_LARGE_FILE_OP_H_

#include "common.h"

namespace qiniu
{
		namespace largefile
		{
				class FileOperation
				{
				public:
					FileOperation(const std::string &file_name, const int open_flags = O_RDWR | O_LARGEFILE);
					~FileOperation();
					
					int open_file();
					void close_file();
					
					int flush_file();  //把文件立即写入到磁盘
					
					int unlink_file(); 
					
					virtual int pread_file(char *buf, const int32_t nbytes, const int64_t offset);
					virtual int pwrite_file(const char *buf,  const int32_t nbytes, const  int64_t offset);  
					
					int write_file(const char *buf, const int32_t nbytes);//seek
					
					int64_t get_file_size();
					
					int ftruncate_file(const int64_t length);
					int seek_file(const int64_t offset);
					
					int get_fd() const 
					{
						return fd_;
					}
					
					protected:
						int fd_;
						int open_flags_;
						char *file_name_;
						
						protected:
						int check_file();
						
					protected:
						static const mode_t  OPEN_MODE = 0644;
						static const int MAX_DISK_TIMES = 5;
	
				};
		}
}

#endif  //QINIU_LARGE_FILE_OP_H_

file_op.cpp:

#include  "file_op.h"
#include "common.h"


namespace qiniu
{
	namespace largefile
	{
		FileOperation::FileOperation(const std::string &file_name, const int open_flags):
		fd_(-1), open_flags_(open_flags)
		{
			file_name_ = strdup(file_name.c_str());
		}
		
		FileOperation::~FileOperation()
		{
			if(fd_ > 0)
			{
				::close(fd_);
			}
			
			if(NULL != file_name_){
				free(file_name_);
				file_name_ = NULL;
			}
		}
		
		int FileOperation::open_file()
		{
			if(fd_ > 0)
			{
				close(fd_);
				fd_=-1;
			}
			
			fd_ = ::open(file_name_, open_flags_, OPEN_MODE);
			if(fd_ < 0)
			{
				return -errno;
			}
			
			return 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;
			
			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  || EAGAIN == -read_len){
						continue;
					}else if(EBADF == -read_len)
					{
						fd_ = -1;
						continue;
					}else {
						return read_len;
					}
				}else if( 0 == read_len)
				{
					break;
				}
				
				left -= read_len;
				p_tmp += read_len;
				read_offset += read_len;
			}
			
			if(0 != left)
			{
				return EXIT_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;
			
			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  || EAGAIN == -written_len){
						continue;
					}else if(EBADF == -written_len)
					{
						fd_ = -1;
						continue;
					}else {
						return written_len;
					}
				}
				
				left -= written_len;
				p_tmp += written_len;
				write_offset += written_len;
			}
			
			if(0 != left)
			{
				return EXIT_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;
			
			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  || EAGAIN == -written_len){
						continue;
					}else if(EBADF == -written_len)
					{
						fd_ = -1;
						continue;
					}else {
						return written_len;
					}
				}
				
				left -= written_len;
				p_tmp += written_len;
				
			}
				
			if(0 != left)
			{
				return EXIT_DISK_OPER_INCOMPLETE;
			}
			
			return TFS_SUCCESS;
		}
		
		
		int64_t FileOperation::get_file_size()
		{
				int fd = check_file();
				
				if(fd < 0)
				{
					return -1;
				}
				
				struct stat statbuf;
				if( fstat(fd, &statbuf) !=0){
					return -1;
				}
				
				return statbuf.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);
			
		}
		
		int FileOperation::flush_file()
		{
			if(open_flags_ & O_SYNC){
				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 qiniu;

int main(void){
	const char * filename = "file_op.txt";
	largefile::FileOperation  *fileOP = new largefile::FileOperation(filename, O_CREAT | O_RDWR | 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, '8', 64);
	int ret = fileOP->pwrite_file(buffer, 64, 128);
	if(ret < 0){
		if(ret == largefile::EXIT_DISK_OPER_INCOMPLETE){
			fprintf(stderr, " pwrite_file: read  length is less than required!");
		}else {
			fprintf(stderr, "pwrite file %s failed. reason: %s\n", filename, strerror(-ret));
		}
	}
	
	memset(buffer, 0, 64);
	ret = fileOP->pread_file(buffer, 64, 128);
	if(ret < 0){
		if(ret ==  largefile::EXIT_DISK_OPER_INCOMPLETE){
			fprintf(stderr, " pread_file: read  length is less than required!");
		}else {
			fprintf(stderr, "pread file %s failed. reason: %s\n", filename, strerror(-ret));
		}
	}else {
		buffer[64] = '\0';
		printf("read: %s\n", buffer);
	}
	
	memset(buffer, '9', 64);
	ret = fileOP->write_file(buffer, 64);
	if(ret < 0){
		if(ret ==  largefile::EXIT_DISK_OPER_INCOMPLETE){
			fprintf(stderr, " write_file: read  length is less than required!");
		}else{
			fprintf(stderr, " write_file %s failed. reason: %s\n", filename, strerror(-ret));
		}
	}

	fileOP->close_file();
	
	return 0;
}

参考资料:

  1. C/C++从入门到精通-高级程序员之路【奇牛学院】
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 次前言 VI 引言 VII 1 范围 1 2 规范性引用文件 1 3 术语和定义 1 4 总则 2 5 电子文件封装结构模型 2 6 封装元数据 2 6.1 封装新增的元数据 2 6.2 依据DA/T 46-2009组配的元数据 3 7 元数据的描述 3 7.1 元数据的描述方法 3 7.2 元数据元素的描述 3 电子文件封装包 3 封装包格式描述 5 版本 5 被签名对象 6 封装包类型 7 封装包类型描述 8 封装包创建时间 9 封装包创建单位 10 封装内容 11 文件实体块 12 文件实体 13 聚合层次 14 来源 15 档案馆名称 15 档案馆代码 15 全宗名称 15 立档单位名称 16 电子文件号 16 档号 16 全宗号 17 目录号 17 年度 17 保管期限 18 机构或问题 18 类别号 18 室编案卷号 18 馆编案卷号 18 室编件号 19 馆编件号 19 页号 19 内容描述 19 题名 21 并列题名 21 副题名 21 说明题名文字 21 主题词 22 关键词 22 人名 22 摘要 22 分类号 22 文件编号 23 责任者 23 日期 23 文种 23 紧急程度 23 主送 24 抄送 24 密级 24 保密期限 24 形式特征 24 文件组合类型 25 页数 25 语种 25 稿本 26 存储位置 26 当前位置 26 脱机载体编号 27 脱机载体存址 27 缩微号 27 权限管理 27 知识产权说明 28 授权 28 授权对象 29 授权行为 29 控制标识 29 信息系统描述 29 附注 29 文件数据 30 文档 30 文档标识符 32 文档序号 32 文档主从声明 33 文档数据 33 编码 34 电子属性 36 格式信息 36 计算机文件名 37 计算机文件大小 37 文档创建程序 37 数字化属性 37 数字化对象形态 38 扫描分辨率 38 扫描色彩模式 38 图像压缩方案 38 编码描述 38 反编码关键字 39 编码数据 40 文件实体关系 41 文件标识符 42 被关联文件标识符 43 关系

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值