文件操作类的实现

1.头文件

#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(); //设计类时要把现实中要实现的接口全部考虑进去,即使这次不用
		                    //方便下次调用时有接口
		 
		 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); //在当前位置写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_

  1. .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()); //strdup作用分配一段内存然后把里面的字符串copy过过去
		}
		
		FileOperation::~FileOperation()
		{
			if(fd_>0)
			{
				::close(fd_);  //c++有个规定,如果函数前面带::表示该函数是全局的,防止产生冲突
			}
			
			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)  //EINTR表示系统繁忙,下次有可能成功
				                                             //EAGAIN表示这次是临时出错,叫你继续尝试
				    {
					    continue;
				    }else if(EBADF == -read_len)    //EBADF表示文件描述符坏了
				    {
					    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)  //EINTR表示系统繁忙,下次有可能成功
				                                             //EAGAIN表示这次是临时出错,叫你继续尝试
				    {
					    continue;
				    }else if(EBADF == -written_len)    //EBADF表示文件描述符坏了
				    {
					    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)  //EINTR表示系统繁忙,下次有可能成功
				                                             //EAGAIN表示这次是临时出错,叫你继续尝试
				    {
					    continue;
				    }else if(EBADF == -written_len)    //EBADF表示文件描述符坏了
				    {
					    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_);
		}
		
		
	}
	
	
	
}

3.通用头文件

#ifndef _common_H_INCLUDED_
#define _common_H_INCLUDED_

#include <iostream>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h>
#include <string>
#include <string.h>   //用strerror()函数必须要包含的头文件
#include <stdint.h>   //使用int32_t 的头文件
#include <stdio.h>    //fprintf()的头文件
#include <errno.h>    //使用errno必须包含的要包含的头文件 
#include <sys/mman.h> //msync的头文件
#include <unistd.h>    //close()函数的头文件
#include <stdlib.h>   //free的头文件


namespace qiniu
{
	namespace largefile
	{
		const int32_t EXIT_DISK_OPER_INCOMPLETE = -8012; //读或者写的长度没有满足要求
		const int32_t TFS_SUCCESS = 0;   //全部读出
	}
}



#endif /*_common_H_INCLUDED_*/

4.调试参考代码


```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,1024);
	
	if(ret<0){
		if(ret == largefile::EXIT_DISK_OPER_INCOMPLETE){
			fprintf(stderr,"pwrite_file: read or write length is less than required!\n");
		}else{
		    fprintf(stderr,"pwrite file %s failed reason:%s\n",filename,strerror(-ret));
		}
	}
	
	memset(buffer,0,64);
	ret = fileOP->pread_file(buffer,64,1024);
	
	if(ret <  0){
		if(ret == largefile::EXIT_DISK_OPER_INCOMPLETE){
			fprintf(stderr,"pread_file: read or write length is less than required!\n");
		}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 or write length is less than required!\n");
		}else{
		    fprintf(stderr,"write_file %s failed reason:%s\n",filename,strerror(-ret));
		}
	}
	
	fileOP->close_file();
	return 0;
}
注释:该代码包含大量的Linux c函数,请在Liunx下调试运行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值