內存映射實戰之文件操作父類頭文件定義
#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_fags = 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);
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_fags_;
char *file_name_;
protected:
int check_file();
protected:
static const mode_t OPEN_MODE = 0644; /* 0: 八進制 */
static const int MAX_DISK_TIMES = 5;
};
}
}
#endif /* */
內存映射實戰之文件操作CPP實現(上)
#include "file_op.h"
#include "common.h"
namespace qiniu
{
namespace largefile
{
FileOperation::FileOperation(const std::string &file_name, const int open_fags):
fd_(-1), open_fags_(open_fags)
{
file_name_ = strdup(file_name.c_str()); /* strdup() 動態內存分配記得要釋放 */
}
FileOperation::~FileOperation()
{
if (fd_ > 0)
{
::close(fd_);
}
if (NULL != file_name_)
{
free(file_name_); /* 釋放第11行strdup()的動態內存分配 */
file_name_ = NULL;
}
}
int FileOperation::open_file()
{
if (fd_ > 0)
{
close(fd_);
fd_ = -1;
}
fd_ = ::open(file_name_, open_fags_, OPEN_MODE);
if (fd_ < 0)
{
return -errno;
}
return fd_;
}
void FileOperation::close_file()
{
if (fd_ < 0)
{
return;
}
::close(fd_);
fd_ = -1;
}
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_fags_ & O_SYNC) /* 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_);
}
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 if (EBADF == -read_len)
{
fd_ = -1;
return read_len;
}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;
}
}
else if (0 == written_len)
{
break;
}
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;
return written_len;
}
else
{
return written_len;
}
}
else if (0 == written_len)
{
break;
}
left -= written_len;
p_tmp += written_len;
}
}
}
}
內存映射實戰之文件操作CPP實現(中)
#ifndef _COMMON_H_INCLUDED_
#define _COMMON_H_INCLUDED_
#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
namespace qiniu
{
namespace largefile
{
const int32_t TFS_SUCCESS = 0;
const int32_t EXIT_DISK_OPER_INCOMPLETE = -8012; /* read or write length is less than required */
}
}
#endif /* _COMMON_H_INCLUDED_ */
#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[4096];
memset(buffer, '6', 4096);
int ret = fileOP->pwrite_file(buffer, 4096, 1024);
if (ret < 0)
{
fprintf(stderr, "pwrite file %s failed reason: %s\n", filename, strerror(-ret));
}
fileOP->close_file();
return 0;
}
demo(一)測試運行結果:
more file_op.txt
demo(二)測試運行結果:
#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[64+1];
memset(buffer, '8', 64);
int ret = fileOP->pwrite_file(buffer, 64, 1024);
if (ret < 0)
{
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)
{
fprintf(stderr, "pread file %s failed reason %s \n", filename, strerror(-ret));
}
else
{
buffer[64] = '\0';
printf("read: %s \n", buffer);
}
fileOP->close_file();
return 0;
}
運行結果:
demo(三)測試運行結果:
#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[64+1];
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 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, 1024);
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 requirend!");
}
else
{
fprintf(stderr, "write_file %s failed reason: %s\n", filename, strerror(-ret));
}
}
fileOP->close_file();
return 0;
}
運行結果:
more file_op.txt
總結:
文件的指針不變, 因此插入的字符, 還是在頭部開始
demo(四)測試運行結果:
#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[64+1];
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 requirend!");
}
else
{
fprintf(stderr, "write_file %s failed reason: %s\n", filename, strerror(-ret));
}
}
fileOP->close_file();
return 0;
}
運行結果:
vi file_op.tx
總結:
文件的指針不變, 因此插入的字符, 還是在頭部開始
結語:
溫馨提示: 請不要用跑步鞋和在有太陽的情況下打球, 打球, 容易扭傷, 我星期五的時候打球(好久沒有和舍友打球, 拉這他們打, 外面太陽溫度有點大, 因爲溫度太高, 所以沒有打超過30分鐘, 沒勁.)
時間: 2020-06-20