diff --git a/README.md b/README.md index 339432d..49bef21 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,12 @@ c/c++基本开发库 # Linux 中屏蔽所有信号操作 屏蔽所有信号,以防止意外退出 + + +# 写文件操作 +允许原文本进行覆盖写,追加写 +允许二进制进行覆盖写,追加写 +允许在特定位置进行写操作 +可以计算特定符号最后一个字节所在位置 + +所有操作都添加mutex锁机制 ,保障线程安全 diff --git a/include/Netra.hpp b/include/Netra.hpp index 2042223..63c5708 100644 --- a/include/Netra.hpp +++ b/include/Netra.hpp @@ -49,7 +49,7 @@ namespace QCL * @param clientSock 客户端Socket描述符 * @param flag:false 非阻塞模式,true 阻塞模式 */ - char *receiveFromClient(int clientSock,bool flag = true); + char *receiveFromClient(int clientSock, bool flag = true); /** * @brief 获取连接客户端的IP和端口 @@ -79,7 +79,116 @@ namespace QCL std::vector clientSockets_; ///< 当前所有连接的客户端Socket集合 }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief 文件写入工具类(线程安全) + * + * 该类支持多种文件写入方式: + * - 覆盖写文本 + * - 追加写文本 + * - 按位置覆盖原文写入 + * - 二进制覆盖写 + * - 二进制追加写 + * + * 特点: + * - 文件不存在时自动创建 + * - 支持覆盖和追加两种模式 + * - 支持二进制模式,适合写入非文本数据 + * - 内部使用 std::mutex 实现线程安全 + */ + class WriteFile + { + public: + /** + * @brief 构造函数 + * @param filePath 文件路径 + */ + explicit WriteFile(const std::string &filePath); + /** + * @brief 覆盖写文本文件(线程安全) + * @param content 要写入的文本内容 + * @return true 写入成功 + * @return false 写入失败 + */ + bool overwriteText(const std::string &content); + + /** + * @brief 追加写文本文件(线程安全) + * @param content 要写入的文本内容 + * @return true 写入成功 + * @return false 写入失败 + */ + bool appendText(const std::string &content); + + /** + * @brief 按指定位置写入文本(原文写,线程安全) + * + * 不清空文件内容,仅替换指定位置的内容。 + * 若文件不存在,则会自动创建空文件。 + * + * @param content 要写入的内容 + * @param position 写入位置(默认为文件开头) + * @return true 写入成功 + * @return false 写入失败 + */ + bool writeOriginal(const std::string &content, std::streampos position = 0); + + /** + * @brief 覆盖写二进制文件(线程安全) + * @param data 要写入的二进制数据 + * @return true 写入成功 + * @return false 写入失败 + */ + bool overwriteBinary(const std::vector &data); + + /** + * @brief 追加写二进制文件(线程安全) + * @param data 要写入的二进制数据 + * @return true 写入成功 + * @return false 写入失败 + */ + bool appendBinary(const std::vector &data); + + /** + * @brief 计算第一个指定字节序列前的字节数(包含该字节序列本身) + * + * 例如:文件内容是 "ABC***--***XYZ",模式是 "***--***" + * 返回值应为 11("ABC"=3字节 + "***--***"=8字节)。 + * + * @param pattern 要查找的字节模式(支持多字节) + * @return long 字节数(包含匹配模式本身),未找到返回 -1 + */ + long countBytesBeforePattern(const std::string &pattern); + + private: + std::string filePath_; ///< 文件路径 + std::mutex writeMutex_; ///< 线程锁,保证多线程写入安全 + + /** + * @brief 通用文本写入接口(线程安全) + * @param content 要写入的内容 + * @param mode 打开模式(追加/覆盖等) + * @return true 写入成功 + * @return false 写入失败 + */ + bool writeToFile(const std::string &content, std::ios::openmode mode); + + /** + * @brief 通用二进制写入接口(线程安全) + * @param data 要写入的二进制数据 + * @param mode 打开模式(追加/覆盖等) + * @return true 写入成功 + * @return false 写入失败 + */ + bool writeBinary(const std::vector &data, std::ios::openmode mode); + }; + + // 读文件操作 + class ReadFile + { + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 屏蔽所有信号 void blockAllSignals(); } diff --git a/src/Netra.cpp b/src/Netra.cpp index 7188325..70aaa2e 100644 --- a/src/Netra.cpp +++ b/src/Netra.cpp @@ -2,6 +2,7 @@ namespace QCL { + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TcpServer::TcpServer(int port) : port_(port), running_(false), serverSock_(-1) {} @@ -215,7 +216,130 @@ namespace QCL snprintf(result, INET_ADDRSTRLEN + 10, "%s:%d", ip, port); return result; } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + WriteFile::WriteFile(const std::string &filePath) + : filePath_(filePath) {} + /** + * @brief 覆盖写文本(线程安全) + */ + bool WriteFile::overwriteText(const std::string &content) + { + std::lock_guard lock(writeMutex_); // 加锁 + return writeToFile(content, std::ios::out | std::ios::trunc); + } + + /** + * @brief 追加写文本(线程安全) + */ + bool WriteFile::appendText(const std::string &content) + { + std::lock_guard lock(writeMutex_); + return writeToFile(content, std::ios::out | std::ios::app); + } + + /** + * @brief 按位置写入(线程安全) + */ + bool WriteFile::writeOriginal(const std::string &content, std::streampos position) + { + std::lock_guard lock(writeMutex_); + + std::ofstream file(filePath_, std::ios::in | std::ios::out); + if (!file.is_open()) + { + // 文件不存在则创建 + file.open(filePath_, std::ios::out); + file.close(); + file.open(filePath_, std::ios::in | std::ios::out); + } + if (!file.is_open()) + return false; + + file.seekp(position); + file << content; + file.close(); + return true; + } + + /** + * @brief 覆盖写二进制(线程安全) + */ + bool WriteFile::overwriteBinary(const std::vector &data) + { + std::lock_guard lock(writeMutex_); + return writeBinary(data, std::ios::out | std::ios::trunc | std::ios::binary); + } + + /** + * @brief 追加写二进制(线程安全) + */ + bool WriteFile::appendBinary(const std::vector &data) + { + std::lock_guard lock(writeMutex_); + return writeBinary(data, std::ios::out | std::ios::app | std::ios::binary); + } + + /** + * @brief 通用文本写入(私有) + */ + bool WriteFile::writeToFile(const std::string &content, std::ios::openmode mode) + { + std::ofstream file(filePath_, mode); + if (!file.is_open()) + return false; + file << content; + file.close(); + return true; + } + + /** + * @brief 通用二进制写入(私有) + */ + bool WriteFile::writeBinary(const std::vector &data, std::ios::openmode mode) + { + std::ofstream file(filePath_, mode); + if (!file.is_open()) + return false; + file.write(data.data(), data.size()); + file.close(); + return true; + } + + /** + * @brief 计算第一个指定字节序列前的字节数(包含该字节序列本身) + */ + long WriteFile::countBytesBeforePattern(const std::string &pattern) + { + std::lock_guard lock(writeMutex_); + + if (pattern.empty()) + return -1; + + std::ifstream file(filePath_, std::ios::binary); // 二进制模式防止编码干扰 + if (!file.is_open()) + return -1; + + // 将整个文件读入内存 + std::vector buffer((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + file.close(); + + // 在 buffer 中查找 pattern + auto it = std::search(buffer.begin(), buffer.end(), + pattern.begin(), pattern.end()); + + if (it == buffer.end()) + { + return -1; // 没找到 + } + + // 计算从开头到 pattern 结束的字节数 + size_t pos = std::distance(buffer.begin(), it); + return static_cast(pos + pattern.size()); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 屏蔽所有信号 void blockAllSignals() { @@ -223,4 +347,5 @@ namespace QCL for (int ii = 1; ii <= 64; ii++) signal(ii, SIG_IGN); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } \ No newline at end of file