轻量级C++数据管理框架 MiniDataX 实现:结构化存储+异步请求+可视化展示
在日常 C++ 开发中,针对中小型结构化数据(如用户信息、商品列表)的管理,往往不需要引入重型数据库或复杂网络库。本文将介绍我(董翔)开发的一个轻量级 C++ 数据管理框架,也就是 MiniDataX,该框架基于原生 C++ 实现,包含结构化数据定义、跨文件数据共享、异步请求模拟、MySQL 风格表格展示四大核心功能,无第三方依赖,可直接集成到项目中使用。
文章目录
一、框架核心定位与适用场景
1. 核心定位
- 轻量级:纯 C++ 原生实现,无任何外部依赖(无需数据库、网络库);
- 模块化:数据存储、业务逻辑、请求处理、可视化展示完全解耦;
- 易扩展:支持自定义数据结构,适配不同业务场景(用户、商品、订单等)。
2. 适用场景
- 中小型结构化数据管理(数据量 1000 条以内);
- 需模拟网络请求的 Demo 或测试项目;
- 嵌入式设备、桌面工具等轻量化数据展示场景;
- 教学场景下的 C++ 模块化、异步编程实践。
二、框架文件结构
框架共包含 5 个核心文件,各文件职责清晰,便于维护和扩展:
mini-data-framework/
├─ util.h // 核心配置文件:数据结构定义、全局变量声明、接口声明
├─ data.db // 数据存储文件:数据初始化、持久化(自定义.db后缀,本质C++源文件)
├─ promise.h // 异步请求核心:Promise类实现,支持异步回调与错误处理
├─ table.cpp // 可视化模块:MySQL风格表格打印实现
└─ main.cpp // 业务入口:请求发起、逻辑串联、框架调用示例
三、核心文件实现详解
1. util.h:框架配置核心
该文件是框架的 “契约中心”,定义数据结构、全局容器和核心接口,使用者只需修改此文件即可适配自身业务。
#ifndef UTIL_H
#define UTIL_H
#include <vector>
#include <string>
// 1. 自定义数据结构(使用者需根据业务修改)
// 示例:商品数据结构(可替换为用户、订单等结构)
typedef struct {
std::string name; // 商品名称
float price; // 商品价格(单位:元)
int stock; // 库存数量
std::string brand; // 品牌
} Product;
// 2. 全局数据容器声明(跨文件共享数据,定义在data.db中)
extern std::vector<Product> g_product_list;
// 3. 核心接口声明(实现分别在data.db、table.cpp中)
// 数据初始化:将初始数据加载到全局容器
void data_init();
// 数据查询:模拟数据库查询,根据URL匹配数据(支持扩展多接口)
std::vector<Product> data_query(const std::string& url);
// 表格打印:将数据以MySQL风格展示
void print_table(const std::vector<Product>& data);
#endif // UTIL_H
2. data.db:数据存储模块
自定义.db后缀标识 “数据文件”,本质是 C++ 源文件,负责数据初始化和持久化(示例含基础初始化,可扩展文件读写)。
#include "util.h"
#include <fstream>
// 全局数据容器定义(与util.h中extern声明对应)
std::vector<Product> g_product_list;
// 初始数据(模拟数据库表数据,可根据业务修改)
const Product g_init_products[] = {
{"iPhone 15", 5999.0f, 120, "Apple"},
{"Mate 60 Pro", 6499.0f, 80, "Huawei"},
{"Xiaomi 14", 4299.0f, 200, "Xiaomi"},
{"OnePlus 12", 4599.0f, 150, "OnePlus"}
};
// 数据初始化:将初始数据加载到全局容器
void data_init() {
int init_count = sizeof(g_init_products) / sizeof(g_init_products[0]);
for (int i = 0; i < init_count; i++) {
g_product_list.push_back(g_init_products[i]);
}
// 扩展:可添加从本地文件加载数据的逻辑(如data.db.dat)
}
// 数据查询:模拟网络接口路由(支持扩展多URL,如/api/user、/api/order)
std::vector<Product> data_query(const std::string& url) {
// 匹配商品查询接口(可扩展其他接口)
if (url == "/api/product") {
return g_product_list;
}
// 未匹配接口返回空数据(触发错误回调)
return std::vector<Product>();
}
3. promise.h:异步请求核心
实现前端 Promise 风格的异步回调机制,支持成功 / 失败回调,模拟网络请求的异步特性。
#ifndef PROMISE_H
#define PROMISE_H
#include <functional>
#include <utility>
// 空类型标识:用于无额外错误信息的场景
struct Undefined {};
// Promise类模板:SuccessT-成功返回类型,FailT-失败返回类型
template <typename SuccessT, typename FailT = Undefined>
class Promise {
public:
// 回调函数类型定义
using ResolveFunc = std::function<void(SuccessT)>;
using RejectFunc = std::function<void(FailT)>;
// 构造函数:接收执行器(包含异步逻辑)
template <typename Executor>
Promise(Executor&& executor) : m_state(PENDING) {
// 包装resolve/reject,传递给执行器
auto resolve = [this](SuccessT value) {
if (m_state != PENDING) return;
m_state = FULFILLED;
m_success_val = std::move(value);
// 触发成功回调
if (m_resolve_func) m_resolve_func(m_success_val);
};
auto reject = [this](FailT value) {
if (m_state != PENDING) return;
m_state = REJECTED;
m_fail_val = std::move(value);
// 触发失败回调
if (m_reject_func) m_reject_func(m_fail_val);
};
// 执行异步逻辑(如模拟网络请求延迟)
executor(std::move(resolve), std::move(reject));
}
// then方法:注册成功/失败回调
Promise& then(ResolveFunc resolve_func, RejectFunc reject_func) {
m_resolve_func = std::move(resolve_func);
m_reject_func = std::move(reject_func);
// 处理同步完成场景(如无网络延迟)
if (m_state == FULFILLED && m_resolve_func) {
m_resolve_func(m_success_val);
} else if (m_state == REJECTED && m_reject_func) {
m_reject_func(m_fail_val);
}
return *this;
}
private:
// Promise状态: pending-等待,fulfilled-成功,rejected-失败
enum State { PENDING, FULFILLED, REJECTED } m_state;
SuccessT m_success_val; // 成功返回值
FailT m_fail_val; // 失败返回值
ResolveFunc m_resolve_func; // 成功回调
RejectFunc m_reject_func; // 失败回调
};
#endif // PROMISE_H
4. table.cpp:可视化模块
实现 MySQL 风格的表格打印,支持自动列对齐、表头自定义,数据展示直观清晰。
#include "util.h"
#include <iostream>
#include <iomanip>
// 辅助函数:计算字符串长度(解决中文乱码问题,英文场景可简化)
int str_length(const std::string& str) {
int len = 0;
for (char c : str) {
len += (c >= 0 && c <= 127) ? 1 : 2; // 中文占2字符,英文占1字符
}
return len;
}
// 打印分隔线(根据列宽动态生成)
void print_separator(const std::vector<int>& col_widths) {
std::cout << "+";
for (int width : col_widths) {
std::cout << std::string(width + 2, '-') << "+";
}
std::cout << std::endl;
}
// 核心:打印MySQL风格表格
void print_table(const std::vector<Product>& data) {
if (data.empty()) {
std::cout << "Empty result set" << std::endl;
return;
}
// 1. 定义表头与列宽(需与数据结构字段对应)
std::vector<std::string> headers = {"Product Name", "Price (Yuan)", "Stock", "Brand"};
std::vector<int> col_widths = {
12, // Product Name列宽
14, // Price列宽
6, // Stock列宽
8 // Brand列宽
};
// 2. 打印表头
print_separator(col_widths);
std::cout << "|";
for (int i = 0; i < headers.size(); i++) {
// 居中对齐(可改为左对齐:left)
std::cout << " " << std::setw(col_widths[i]) << std::left << headers[i] << " |";
}
std::cout << std::endl;
print_separator(col_widths);
// 3. 打印数据行
for (const auto& item : data) {
std::cout << "|";
// 商品名称(左对齐)
std::cout << " " << std::setw(col_widths[0]) << std::left << item.name << " |";
// 价格(保留1位小数,右对齐)
std::cout << " " << std::setw(col_widths[1]-1) << std::right << std::fixed << std::setprecision(1) << item.price << " |";
// 库存(右对齐)
std::cout << " " << std::setw(col_widths[2]) << std::right << item.stock << " |";
// 品牌(左对齐)
std::cout << " " << std::setw(col_widths[3]) << std::left << item.brand << " |";
std::cout << std::endl;
}
print_separator(col_widths);
// 4. 打印数据统计
std::cout << data.size() << " rows in set" << std::endl;
}
5. main.cpp:业务入口示例
演示框架的完整调用流程:初始化数据→发起异步请求→处理回调(成功打印表格 / 失败提示)。
#include "util.h"
#include "promise.h"
#include <iostream>
// 模拟网络请求:返回Promise对象(异步逻辑封装)
Promise<std::vector<Product>, Undefined> send_request(const std::string& url) {
return Promise<std::vector<Product>, Undefined>([&](auto resolve, auto reject) {
// 模拟网络请求延迟(可注释,直接同步返回)
// std::this_thread::sleep_for(std::chrono::seconds(1));
// 调用数据查询接口
std::vector<Product> result = data_query(url);
if (!result.empty()) {
// 请求成功:返回查询结果
resolve(result);
} else {
// 请求失败:返回空错误(Undefined)
reject(Undefined());
}
});
}
int main() {
// 1. 初始化数据(加载初始商品数据)
data_init();
std::cout << "Data initialized successfully!" << std::endl;
// 2. 发起异步请求(示例1:请求存在的接口)
std::cout << "\nRequesting /api/product..." << std::endl;
send_request("/api/product")
.then(
// 成功回调:打印表格
[](std::vector<Product> data) {
print_table(data);
},
// 失败回调:提示错误
[](Undefined) {
std::cout << "Request failed: URL not found!" << std::endl;
}
);
// 3. 发起异步请求(示例2:请求不存在的接口,触发失败回调)
std::cout << "\nRequesting /api/order..." << std::endl;
send_request("/api/order")
.then(
[](std::vector<Product> data) {
print_table(data);
},
[](Undefined) {
std::cout << "Request failed: URL not found!" << std::endl;
}
);
return 0;
}
四、框架编译与运行
1. 编译命令(GCC/Clang)
由于.db文件本质是 C++ 源文件,编译时需将其与其他文件一同编译:
# 编译所有源文件,生成可执行文件mini-framework
g++ main.cpp data.db table.cpp -o mini-framework -std=c++11
2. 运行效果
Data initialized successfully!
Requesting /api/product...
+----------------------+------------------+--------+----------+
| Product Name | Price (Yuan) | Stock | Brand |
+----------------------+------------------+--------+----------+
| iPhone 15 | 5999.0 | 120 | Apple |
| Mate 60 Pro | 6499.0 | 80 | Huawei |
| Xiaomi 14 | 4299.0 | 200 | Xiaomi |
| OnePlus 12 | 4599.0 | 150 | OnePlus |
+----------------------+------------------+--------+----------+
4 rows in set
Requesting /api/order...
Request failed: URL not found!
五、框架扩展指南
1. 适配自定义数据(如用户信息)
- 修改
util.h中的Product结构体为User:
typedef struct {
std::string id; // 用户ID
std::string name; // 用户名
int age; // 年龄
std::string email; // 邮箱
} User;
- 更新
data.db中的初始数据和全局容器(g_user_list); - 调整
table.cpp的表头、列宽和数据打印逻辑,适配User字段。
2. 扩展持久化功能(本地文件读写)
在data.db中添加文件读写函数,支持数据持久化到本地(如user_data.dat):
// 从文件加载数据
void load_from_file(const std::string& filename) {
std::ifstream file(filename);
User user;
while (file >> user.id >> user.name >> user.age >> user.email) {
g_user_list.push_back(user);
}
file.close();
}
// 保存数据到文件
void save_to_file(const std::string& filename) {
std::ofstream file(filename);
for (const auto& user : g_user_list) {
file << user.id << " " << user.name << " " << user.age << " " << user.email << std::endl;
}
file.close();
}
3. 增加多接口支持
在data.db的data_query函数中添加新 URL 路由,支持多业务接口:
std::vector<User> data_query(const std::string& url) {
if (url == "/api/user") {
return g_user_list; // 用户接口
} else if (url == "/api/user/vip") {
// 筛选VIP用户(扩展业务逻辑)
std::vector<User> vip_users;
for (const auto& user : g_user_list) {
if (user.age > 25) { // 示例:年龄>25视为VIP
vip_users.push_back(user);
}
}
return vip_users;
}
return std::vector<User>();
}
六、总结
本框架以 “轻量化、模块化、易扩展” 为核心,用原生 C++ 实现了结构化数据管理的完整流程。通过自定义数据结构、异步请求封装和可视化展示,既满足了中小型数据的管理需求,又避免了重型依赖带来的复杂性。
框架的核心优势在于 “配置简单、上手快”,开发者只需修改util.h和data.db即可适配自身业务,无需关注 Promise 异步机制和表格打印的底层实现,大幅降低了轻量化数据管理场景的开发成本。
更多推荐

所有评论(0)