[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
- [Muduo网络库源码分析] (5) base/FileUtil.cc_h_文件操作
- [Muduo网络库源码分析] (2) base/Condition.cc_h_条件变量操作
- [Muduo网络库源码分析] (3) base/CountDownLatch.cc_h_“倒计时门闩”同步
- muduo库源码学习(base)FileUtil
- [Muduo网络库源码分析] (1) base/Atomic.h_原子操作与原子整数
- [Muduo网络库源码分析] (6) base/Mutex.h_互斥锁操作
- [Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
- muduo::FileUtil、LogFile分析
- [Muduo网络库源码分析] (4) base/Exception_cc_h_带 stack trace 的异常基类
- [Muduo网络库源码分析] (7) base/Singleton.h_SINGLETON对象创建型模式
- [Muduo网络库源码分析] (8) base/StringPiece.h_字符串参数传递类型
- [Muduo网络库源码分析] (9) base/Thread.cc_h_CurrentThread_h线程对象
- [Muduo网络库源码分析] (11) base/Types.h_基本类型声明
- muduo网络库源码分析-定时器
- muduo库源码分析
- muduo库源码学习(base)Atomic
- muduo库源码学习(base)AsyncLogging
- muduo库源码学习(base)Condition
- 关于RecyclerView列表点击事件ripple效果失效的问题
- 深搜 加奇偶剪枝
- jQuery获取格式化当前时间
- Kotlin Reference (三) Coding Conventions
- 雷军给程序员的五点建议--如何成为编程高手并以此创业
- [Muduo网络库源码分析] (5) base/FileUtil.cc_h_文件操作
- Scala定义函数的5种方式
- 有关数组的基础递归
- 改变this指向(call、apply、bind)
- cannot simultaneously fetch multiple bags[]不能抓取一对多的属性
- iOS pop到指定页面
- struts2把action交给spring托管
- 一个邮件钓鱼木马的分析 (一)
- 上拉加载