基础文件操作类

创建文件操作的头文件

这个类设计的目的是提供一个简单而全面的接口,以便进行常见的大文件操作。它封装了文件的打开、关闭、读写等基本操作,使得在应用程序中更容易使用和维护。

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();
}


测试结果:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值