C++实现文件操作类

总的来说,这是一个非常优秀、健壮且线程安全的文件操作类设计。 成功地应用了 C++ 的核心特性(如继承、多态、RAII、std::mutex等)来解决实际问题。

下面我将进行一个全面的回顾,并提出一些非常细微的建议,这些建议更多是关于代码风格和潜在的边缘情况处理。

代码亮点(总结)

设计模式:正确使用了 ** 接口类(FileBase)和实现类(TextFile)** 的设计模式,通过纯虚函数定义了清晰的契约。

线程安全:TextFile 类内部使用了 std::mutex 和 std::lock_guard 来保护所有对共享资源(file_stream_, is_open_)的访问,实现了线程安全。

资源管理:严格遵守RAII原则。

析构函数会自动调用 Close(),确保文件被关闭,资源被释放。

Open() 和 Close() 方法正确地管理了 file_stream_ 和 is_open_ 的状态。

错误处理:Write 和 WriteLine 方法通过检查 file_stream_.fail() 来判断操作是否成功,并返回 bool 值,让调用者可以处理失败情况。

封装性:

FileBase 中的 filename_ 为 protected,允许子类访问,同时防止外部直接修改。

TextFile 的成员变量 mutex_, file_stream_, is_open_ 均为 private,保证了类的内部状态不会被外部随意篡改。

虚析构函数:FileBase 正确地声明了 virtual ~FileBase() = default;,确保了通过基类指针删除子类对象时的行为是正确的。

cpp 复制代码
#include <string>
#include <ios>
class FileBase
{
public:
    FileBase() = default;
    virtual ~FileBase() = default;
    virtual bool Open(const std::string &fileName, std::ios_base::openmode mode) = 0;
    virtual void Close() = 0;
    virtual void Flush() = 0;
    virtual bool IsOpen() const = 0;
    virtual bool Write(const std::string & data) = 0;
    virtual bool WriteLine(const std::string & line) = 0;
    virtual std::string Read() = 0;
    virtual std::string ReadLine() = 0;
protected:
    std::string filename_;
};
cpp 复制代码
#include <fstream>
#include <mutex>
#include "file_base.hpp"
class TextFile :public FileBase
{
private:
    mutable std::mutex mutex_;
    std::fstream file_stream_;
    bool is_open_; 
public:
    TextFile();
    ~TextFile();
    bool Open(const std::string &fileName,
        std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) override;
    void Close() override;
    void Flush() override;
    bool IsOpen() const override;
    bool Write(const std::string & data) override;
    bool WriteLine(const std::string & line)override;
    std::string Read() override;
    std::string ReadLine() override;
};
cpp 复制代码
#include "file_text.hpp"
#include <sstream>

TextFile::TextFile():file_stream_(),is_open_(false)
{
}

TextFile::~TextFile()
{
    Close();
}

bool TextFile::Open(const std::string &fileName,std::ios_base::openmode mode) {
    std::lock_guard<std::mutex> lock(mutex_);
    //如果TextFile对象已经打开一个文件,再次调用open会失败,fstream对象不能同时打开多个文件
    //如果已打开其他文件,先关闭
    if(is_open_){
        file_stream_.close();
    }
    file_stream_.open(fileName, mode);
    is_open_ = file_stream_.is_open();
    if(is_open_){
        filename_ = fileName;
    }
    return is_open_;
}
void TextFile::Close(){
    std::lock_guard<std::mutex> lock(mutex_);
    if(is_open_){
        file_stream_.close();
        is_open_ = false;
    }
}

void TextFile::Flush(){
    std::lock_guard<std::mutex> lock(mutex_);
    if(is_open_)
        file_stream_.flush();//文件未打开,调用flush不会崩溃,但也是一个无意义的操作
}

bool TextFile::IsOpen() const{
    //这里要加锁,防止另一个线程正在写,这时候读会产生未定义行为
    std::lock_guard<std::mutex> lock(mutex_);
    return is_open_;
}

bool TextFile::Write(const std::string& data){
    std::lock_guard<std::mutex> lock(mutex_);
    if(!is_open_) return false;
    file_stream_ << data; //如果磁盘已满,写入会失败
    return !file_stream_.fail();
}

bool TextFile::WriteLine(const std::string & line){
    std::lock_guard<std::mutex> lock(mutex_);
    if(!is_open_) return false;
    file_stream_ << line << '\n';
    return !file_stream_.fail();
}

std::string TextFile::Read(){
    std::lock_guard<std::mutex> lock(mutex_);
    if(!is_open_) return "";
    std::ostringstream ss;
    ss << file_stream_.rdbuf();
    return ss.str();
}

std::string TextFile::ReadLine(){
    std::lock_guard<std::mutex> lock(mutex_);
    if(!is_open_) return "";
    std::string line;
    if(getline(file_stream_,line)){
        return line;
    }else{
        return "";
    }
}
相关推荐
小七在进步6 分钟前
C++入门(2)
java·jvm·c++
en.en..34 分钟前
C语言核心解析:#define与typedef本质区别
开发语言·c++·算法
2601_9669496541 分钟前
批量获取多只股票五档盘口的极简方案:QuantDash Python SDK 实战指南
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
码匠许师傅1 小时前
【设计模式精讲】26.策略模式(Strategy)
c++·设计模式·策略模式·uml
点心的游戏开发世界1 小时前
GDScript 入门笔记:目录
开发语言·笔记·游戏引擎·godot
洋不写bug2 小时前
二叉树(二) 常见基础操作解析|结点数、树高、查找结点、判断完全二叉树
java·开发语言·数据结构·完全二叉树·二叉树结点数·树高·查找结点
果果燕2 小时前
实习笔记(六)主机按钮状态上报完整流程
开发语言·c++·php
平头哥技术团队2 小时前
Day 16 | 用 ul、ol、li 一个标签,把散资料收成有序的技能清单页
开发语言·前端·html·html5
是个西兰花2 小时前
网络基础1
linux·网络·c++·智能路由器
统计学小王子2 小时前
数学建模国赛倒计时 2 天 ——《统计模型精讲(广义线性模型 R 语言实例 + 分析)》
开发语言·数学建模·r语言