muduo库源码学习(base)FileUtil

来源:互联网 发布:mac能用qq旋风吗 编辑:程序博客网 时间:2024/06/05 23:44
class ReadSmallFile : boost::noncopyable{ public:  ReadSmallFile(StringArg filename);  ~ReadSmallFile();  // return errno  template<typename String>  int readToString(int maxSize,//最大的长度                   String* content,//dest                   int64_t* fileSize,//文件大小                   int64_t* modifyTime,//修改大小                   int64_t* createTime); //创建时间  /// Read at maxium kBufferSize into buf_  // return errno  int readToBuffer(int* size);  const char* buffer() const { return buf_; }  static const int kBufferSize = 64*1024; private:  int fd_;  int err_;  char buf_[kBufferSize];};// read the file content, returns errno if error happens.template<typename String>int readFile(StringArg filename,//读取文件,是对ReadSmallFile的一个包装。             int maxSize,             String* content,             int64_t* fileSize = NULL,             int64_t* modifyTime = NULL,             int64_t* createTime = NULL){  ReadSmallFile file(filename);  return file.readToString(maxSize, content, fileSize, modifyTime, createTime);}// not thread safeclass AppendFile : boost::noncopyable{ public:  explicit AppendFile(StringArg filename);  ~AppendFile();  void append(const char* logline, const size_t len);  void flush();  size_t writtenBytes() const { return writtenBytes_; } private:  size_t write(const char* logline, size_t len);  FILE* fp_;  char buffer_[64*1024];  size_t writtenBytes_;};


FileUtil::AppendFile::AppendFile(StringArg filename)  : fp_(::fopen(filename.c_str(), "ae")),  // 'e' for O_CLOEXEC//这里用了fopen    writtenBytes_(0){  assert(fp_);  ::setbuffer(fp_, buffer_, sizeof buffer_);//设置缓冲区  // posix_fadvise POSIX_FADV_DONTNEED ?}FileUtil::AppendFile::~AppendFile(){  ::fclose(fp_);}void FileUtil::AppendFile::append(const char* logline, const size_t len){  size_t n = write(logline, len);//调用fwrite  size_t remain = len - n;  while (remain > 0)  {    size_t x = write(logline + n, remain);    if (x == 0)    {      int err = ferror(fp_);      if (err)      {        fprintf(stderr, "AppendFile::append() failed %s\n", strerror_tl(err));      }      break;    }    n += x;    remain = len - n; // remain -= x  }  writtenBytes_ += len;}void FileUtil::AppendFile::flush()//立刻刷新{  ::fflush(fp_);}size_t FileUtil::AppendFile::write(const char* logline, size_t len){  // #undef fwrite_unlocked  return ::fwrite_unlocked(logline, 1, len, fp_);}FileUtil::ReadSmallFile::ReadSmallFile(StringArg filename)  : fd_(::open(filename.c_str(), O_RDONLY | O_CLOEXEC)),//构造函数打开文件    err_(0){  buf_[0] = '\0';  if (fd_ < 0)  {    err_ = errno;  }}FileUtil::ReadSmallFile::~ReadSmallFile(){  if (fd_ >= 0)//文件描述符有效则关闭  {    ::close(fd_); // FIXME: check EINTR  }}// return errnotemplate<typename String>int FileUtil::ReadSmallFile::readToString(int maxSize,//将文件读到content                                          String* content,                                          int64_t* fileSize,                                          int64_t* modifyTime,                                          int64_t* createTime){  BOOST_STATIC_ASSERT(sizeof(off_t) == 8);  assert(content != NULL);  int err = err_;  if (fd_ >= 0)  {    content->clear();    if (fileSize)//那为什么content就不检查呢?    {      struct stat statbuf;//获取文件信息      if (::fstat(fd_, &statbuf) == 0)      {        if (S_ISREG(statbuf.st_mode))//是文件        {          *fileSize = statbuf.st_size;//文件大小          content->reserve(static_cast<int>(std::min(implicit_cast<int64_t>(maxSize), *fileSize)));//预留大小。取文件和可读的max的min        }        else if (S_ISDIR(statbuf.st_mode))//是目录        {          err = EISDIR;        }        if (modifyTime)//保存修改时间        {          *modifyTime = statbuf.st_mtime;        }        if (createTime)//创建时间        {          *createTime = statbuf.st_ctime;        }      }      else      {        err = errno;      }    }    while (content->size() < implicit_cast<size_t>(maxSize))//也就是上面的比较结果,可读的最大值超过文件大小,那就尝试读到最大    {//思想就是尽量多地读      size_t toRead = std::min(implicit_cast<size_t>(maxSize) - content->size(), sizeof(buf_));      ssize_t n = ::read(fd_, buf_, toRead);      if (n > 0)//读出n字节后,追加到content      {        content->append(buf_, n);      }      else//n==0表示读到文件末尾      {        if (n < 0)//出错        {          err = errno;        }        break;      }    }  }  return err;}int FileUtil::ReadSmallFile::readToBuffer(int* size){  int err = err_;  if (fd_ >= 0)  {    ssize_t n = ::pread(fd_, buf_, sizeof(buf_)-1, 0);//读文件到buf,size是实际读出的大小。@4是文件偏移游标。    if (n >= 0)    {      if (size)      {        *size = static_cast<int>(n);      }      buf_[n] = '\0';    }    else    {      err = errno;    }  }  return err;}template int FileUtil::readFile(StringArg filename,                                int maxSize,                                string* content,                                int64_t*, int64_t*, int64_t*);template int FileUtil::ReadSmallFile::readToString(    int maxSize,    string* content,    int64_t*, int64_t*, int64_t*);#ifndef MUDUO_STD_STRINGtemplate int FileUtil::readFile(StringArg filename,                                int maxSize,                                std::string* content,                                int64_t*, int64_t*, int64_t*);template int FileUtil::ReadSmallFile::readToString(    int maxSize,    std::string* content,    int64_t*, int64_t*, int64_t*);#endif