[Muduo网络库源码分析] (5) base/FileUtil.cc_h_文件操作

来源:互联网 发布:中国网络资讯台无锡市 编辑:程序博客网 时间:2024/06/10 07:46

文件操作

实现:ReadSmallFile、AppendFile


功能:实现文件内容、信息的读取与写入


知识点:

  • fwrite_unlocked
    fwrite 和 fwrite_unlocked是一对,其中fwrite_unlocked是fwrite的线程不安全版本,因为不加锁。

  • O_CLOEXEC
    调用open函数O_CLOEXEC模式打开的文件描述符在执行exec调用新程序中关闭,且为原子操作

  • pread()
    //pread() reads up to count bytes from file descriptor fd at offset offset (from the start of the file) into the buffer starting at buf. The file offset is not changed.


用途:

可用于文件读取与写入,可用于日志的写入

模块拆分与封装:

已把其文件读取模块单独分离出来,并利用Makefile统一编译,模块代码地址如下:https://github.com/chudongfang/Learn_From_Muduo/tree/master/FileRead


代码及分析:

FileUtil.cc

// Copyright 2010, Shuo Chen.  All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//#include <muduo/base/FileUtil.h>#include <muduo/base/Logging.h> // strerror_tl#include <boost/static_assert.hpp>#include <assert.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <sys/stat.h>using namespace muduo;//构造函数FileUtil::AppendFile::AppendFile(StringArg filename)  : fp_(::fopen(filename.c_str(), "ae")),  // 'e' for O_CLOEXEC    writtenBytes_(0){  assert(fp_);  //设置缓冲区  ::setbuffer(fp_, buffer_, sizeof buffer_);  // posix_fadvise POSIX_FADV_DONTNEED ?}//析构函数FileUtil::AppendFile::~AppendFile(){  //关闭文件  ::fclose(fp_);}//向文件中写长度len的loglinevoid FileUtil::AppendFile::append(const char* logline, const size_t len){  //写入文件  size_t n = write(logline, len);  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代表已经写入的数    n += x;    //remain代表还需写入的数    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_);}//读文件构造函数,在此期间打开文件,并记录文件描述符//调用open函数O_CLOEXEC模式打开的文件描述符在执行exec调用新程序中关闭,且为原子操作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 errno// 获取文件信息,并把文件内容读入到content中template<typename String>int FileUtil::ReadSmallFile::readToString(int maxSize,                                          String* content,                                          int64_t* fileSize,                                          int64_t* modifyTime,                                          int64_t* createTime){  //编译期间断言  long int 是否占八位  BOOST_STATIC_ASSERT(sizeof(off_t) == 8);  assert(content != NULL);  int err = err_;  if (fd_ >= 0)  {     //清空    content->clear();    if (fileSize)    {      //获取文件信息到statbut      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)));        }        //是否是一个目录        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_));      //long      ssize_t n = ::read(fd_, buf_, toRead);      if (n > 0)      {        content->append(buf_, n);      }      else      {        if (n < 0)        {          err = errno;        }        break;      }    }  }  return err;}//把文件中的内容读进缓冲区,并给size赋值为文件的大小int FileUtil::ReadSmallFile::readToBuffer(int* size){  int err = err_;  if (fd_ >= 0)  {    //pread()  reads  up to count bytes from file descriptor fd at offset offset (from the start of the    //file) into the buffer starting at buf.  The file offset is not changed.    ssize_t n = ::pread(fd_, buf_, sizeof(buf_)-1, 0);    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

FileUtil.h

// Copyright 2010, Shuo Chen.  All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is a public header file, it must only include public header files.#ifndef MUDUO_BASE_FILEUTIL_H#define MUDUO_BASE_FILEUTIL_H#include <muduo/base/StringPiece.h>#include <boost/noncopyable.hpp>namespace muduo{namespace FileUtil{//用来读取小文件// read small file < 64KBclass ReadSmallFile : boost::noncopyable{ public:  //构造函数  ReadSmallFile(StringArg filename);  ~ReadSmallFile();  // return errno  //读文件到缓冲区,并获取文件信息  template<typename String>  int readToString(int maxSize,                   String* content,                   int64_t* fileSize,                   int64_t* modifyTime,                   int64_t* createTime);  /// Read at maxium kBufferSize into buf_  // return errno  //读文件到缓冲区,并将size值置为文件大小  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,             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();  //向文件追加长度n的logline  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_;};}}#endif  // MUDUO_BASE_FILEUTIL_H
阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 京东过了7天退货怎么办 同款衣服比京东便宜怎么办 国美不让休班还不给加班钱怎么办 在国美电器买贵商品怎么办 给民俗差评老板骂你怎么办 华为p10后置摄像头调黑了怎么办 美图m6手机相机拍照模糊该怎么办 美图t8用久了卡怎么办 美图m4手机开不开机怎么办 比亚迪m6冷凝器散热不好怎么办 深圳市小汽车摇号审核没通过怎么办 扫码开门售货机拿了不给钱怎么办 预付卡办完后对方不愿退款怎么办 海尔88u52显示內存不足怎么办 京东账号绑定的手机好不用了怎么办 京东账号换手机了手机号没变怎么办 京东发票的号和手机对不起来怎么办 京东账号忘记了只有身份证怎么办啊 京东账号手机号换了忘记账号怎么办 新换的卡被注册过京东号怎么办 以旧换新旧的没给商家报案怎么办 宜家家居家居指南地址写错怎么办 苏宁任性付没还遭到恐吓心意怎么办 大王卡激活后一直是E网怎么办 京东退货已取走后悔了怎么办 退差价把下单立返红包退还了怎么办 苏宁电器发票丢了换电器怎么办 苹果5s访问限制密码忘了怎么办 京东买的暴风电视出现问题了怎么办 控水一个月的三角梅还没开花怎么办 帮别人办手机分期不还怎么办 国美在线没有信用卡分期不了怎么办 手机店办理分期被老板套现了怎么办 美的空调保修卡丢了怎么办 格力空调保修卡丢了怎么办 荣耀9i手机总是滑手怎么办? 春兰空调没发票不给修怎么办 洗衣机顶盖的安全开关坏了怎么办 苹果手机的开关健坏了怎么办 淘宝买的东西快递弄破损了怎么办 京东购买邮来手机里面没有怎么办