如何在C++中使用Boost直接解析含JSON片段的日志文件?
问题:直接用C++ Boost解析含JSON片段的日志文件
日志行示例如下:
[2020-08-23 19:19:29.137] [exchange_tools] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212350,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187624,"prev_seq_num": 111529187575,"asks": [],"bids": [[11666.14, 6.752865]]}
需要提取JSON片段中的type、event_time、asks、bids字段。当前方案是先用Python截取每行中"Object: "后的JSON内容并保存为JSON文件,再用Boost读取:
boost::property_tree::ptree pt; std::ifstream json_in("outfile.json"); std::string line_json; while (std::getline(json_in, line_json)) { std::stringstream ss; ss << line_json; boost::property_tree::read_json(ss, pt); std::cout << pt.get<std::string>("type") << std::endl; }
希望去掉Python步骤,直接在C++中用Boost完成日志解析,该如何实现?
解决方案
核心思路是:读取日志文件的每一行,先定位并截取"Object: "之后的JSON内容,再用Boost.PropertyTree解析这段JSON并提取目标字段。
完整实现代码
#include <iostream> #include <fstream> #include <string> #include <sstream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> namespace pt = boost::property_tree; int main() { // 打开目标日志文件 std::ifstream log_file("your_log_file.log"); if (!log_file.is_open()) { std::cerr << "无法打开日志文件!" << std::endl; return 1; } std::string log_line; const std::string marker = "Object: "; while (std::getline(log_file, log_line)) { // 定位JSON片段的起始位置 size_t json_start_pos = log_line.find(marker); if (json_start_pos == std::string::npos) { // 跳过不包含目标JSON的行 continue; } // 截取完整的JSON字符串 std::string json_str = log_line.substr(json_start_pos + marker.length()); // 解析JSON并提取字段 pt::ptree pt; try { std::stringstream ss(json_str); pt::read_json(ss, pt); // 提取基础字段 std::string type = pt.get<std::string>("type"); uint64_t event_time = pt.get<uint64_t>("event_time"); // 输出基础字段 std::cout << "类型: " << type << std::endl; std::cout << "事件时间: " << event_time << std::endl; // 处理数组类型的asks std::cout << "卖单列表: ["; for (const auto& ask : pt.get_child("asks")) { std::cout << "("; // 遍历数组内的元素(示例为数值类型) for (const auto& val : ask.second) { std::cout << val.second.get_value<double>() << ", "; } std::cout << "), "; } std::cout << "]" << std::endl; // 处理二维数组类型的bids std::cout << "买单列表: ["; for (const auto& bid : pt.get_child("bids")) { std::cout << "("; for (const auto& val : bid.second) { std::cout << val.second.get_value<double>() << ", "; } std::cout << "), "; } std::cout << "]" << std::endl; std::cout << "-------------------------" << std::endl; } catch (const std::exception& e) { std::cerr << "解析JSON失败: " << e.what() << std::endl; continue; } } log_file.close(); return 0; }
关键说明
- 定位JSON片段:用
std::string::find找到"Object: "的位置,再通过substr截取后续内容,自动跳过不符合格式的日志行。 - 异常处理:用
try-catch包裹JSON解析逻辑,避免因日志格式错误导致程序崩溃。 - 数组字段处理:
asks和bids为数组类型,通过遍历pt.get_child()返回的子节点集合访问元素,针对二维数组(如bids)做嵌套遍历。 - 编译注意:编译时需链接Boost库,例如GCC命令:
g++ -o log_parser log_parser.cpp -lboost_system -lboost_property_tree
内容的提问来源于stack exchange,提问作者wwqeee
相关产品推荐
相关产品推荐

