c++如何实现简单的键值对文件存储_类似Redis的持久化【实战】

夜枫大大_9497

夜枫大大_9497

2026-04-09

761人浏览

原创

用 std::map + 制表符分隔的文本序列化实现轻量键值持久化:内存用 std::map 管理,落盘时每行写为 key value,避免 value 含等号导致解析错误。

c++如何实现简单的键值对文件存储_类似redis的持久化【实战】

用 std::map + 文本序列化实现最简键值持久化

不依赖第三方库、不启动服务,就是读写一个本地文件,存几条 key=value。核心思路是:内存用 std::map<:string std::string> 管理,落盘时逐行写成 key value(用制表符分隔,比等号更安全,避免 value 含 = 时解析错位)。

常见错误是直接用 operator 写 std::string,但没处理换行、制表符、反斜杠等特殊字符——结果一存带 的 value,下次就解析错行。必须做转义:

  • 写入前对 key 和 value 分别调用转义函数:把 → \t, → \n,\ → \\
  • 读取时按行分割后,再反向还原这些转义(注意顺序:先还原 \\,再 \n,再 \t,否则会套娃)
  • 文件编码默认用 UTF-8,不指定 locale,避免 Windows 下 ofstream 默认 ANSI 导致中文乱码

用 std::fstream 安全覆盖写入,避免崩溃丢数据

直接 std::ofstream f("db.txt"); f 看似简单,但进程崩溃或断电时,原文件可能被清空、新内容只写一半。正确做法是「写临时文件 + 原子重命名」:

  • 生成临时路径,如 db.txt.tmp_$$($$ 替换为当前进程 ID)
  • 用 std::ofstream 打开临时文件,设置 f.exceptions(std::ios::failbit | std::ios::badbit),确保写失败立刻抛异常
  • 全部写完后,调用 std::filesystem::rename("db.txt.tmp_1234", "db.txt")(C++17 起支持)
  • 如果 rename 失败(比如跨磁盘),则 fallback 到手动 copy + delete,但概率极低

注意:Windows 下 rename 要求目标文件不存在,所以得先 remove("db.txt") 再 rename;Linux/macOS 允许覆盖,可省一步。

加载时跳过空行、注释和格式错误行

用户手改配置文件很常见,不能因某一行少个 就整个加载失败。解析逻辑要宽容:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 用 std::getline() 逐行读,line.empty() || line[0] == '#' 直接跳过
  • 用 line.find(' ') 找第一个制表符位置,没找到就跳过该行(不报错)
  • 取 key = line.substr(0, pos),value = line.substr(pos+1),再分别 unescape
  • 如果 unescape 过程出错(比如 \z 无法识别),把该 value 当原始字符串保留,不中断后续行

这样即使文件末尾多了一行乱码,也不影响前面 99 条正常数据的加载。

性能瓶颈在频繁刷盘?用脏标记 + 延迟写入

每次 set("a", "1") 都写磁盘,几百次操作就卡住。加一层缓存控制:

  • 内部维护一个 bool dirty = false 标记,set() / del() 后置为 true
  • 提供 save() 显式刷盘,以及 ~DB() { if (dirty) save(); } 保底
  • 不推荐定时自动 save(比如每 5 秒),因为 C++ 没可靠后台线程机制,且用户未必需要
  • 如果真要高频写,可改用追加模式(append-only log),但解析就得从头扫文件——简单场景没必要

真正容易被忽略的是:std::filesystem::rename 在某些 NFS 或容器挂载卷上可能不原子,此时应检测是否同设备(statfs),否则 fallback 到 copy + delete,并接受短暂的「两份数据」窗口期。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

2025.09.05

670

5

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.16

343

7

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.17

533

20

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.27

303

6

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4809

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

4355

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

8332

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

663

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

776

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习