Мне нужно разобрать файл журнала на C++. У меня есть этот образец строки из этого файла:
[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 мне нужно: "тип", "время_события", "спросы", "ставки".
Мое текущее решение: для каждой строки в файле удалить первые символы от начала до «Объект:» на python.
{"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, прочитанный для каждой строки в C++:
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;
}
У меня это работает, но я хочу разобрать файл журнала на C++ (ускорение) без использования python. Как я могу это сделать?
Во-первых, не злоупотребляйте деревом свойств для поддержки JSON или XML. Вместо этого используйте Boost JSON.
Во-вторых, конечно, вы можете выполнять манипуляции со строками на C++. Вот пример, который должно быть легко расширить:
#include <boost/fusion/adapted/struct.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/spirit/home/x3.hpp>
struct Record {
std::string time, source, level, msg;
};
using Records = std::vector<Record>;
BOOST_FUSION_ADAPT_STRUCT(Record, time, source, level, msg)
namespace Parser {
using namespace boost::spirit::x3;
auto bracketed = rule<struct _, std::string>{"bracketed"}
= '[' >> raw[*~char_(']')] >> ']';
auto time = bracketed; // perhaps refine
auto source = bracketed; // perhaps refine
auto level = bracketed; // perhaps refine
auto msg = lexeme[*(char_ - eol)]; // perhaps refine
auto record = rule<struct record, Record>{"record"}
= time >> source >> level >> msg;
auto records = *(record >> (+eol | eoi));
auto file = skip(blank)[records] >> eoi;
} // namespace Parser
Records ParseRecords(std::string const& fname) {
Records records;
boost::iostreams::mapped_file_source file(fname);
if (!parse(file.begin(), file.end(), Parser::file, records))
throw std::runtime_error("Parsing failed\n");
return records;
}
#include <boost/json/src.hpp> // for header-only
#include <iostream>
namespace json = boost::json;
int main() {
for (auto& r : ParseRecords("input.txt")) {
std::string_view payload = r.msg;
if (payload.starts_with("Get Object: ")) {
auto obj = json::parse(payload.substr(12));
std::cout << " -----\n"
<< " Level: " << r.level << "\n"
<< " Time: " << r.time << "\n"
<< " Source: " << r.source << "\n"
<< " Type: " << obj.at("type") << "\n"
<< " Event Time: " << obj.at("event_time") << "\n"
<< " Asks: " << obj.at("asks") << "\n"
<< " Bids: " << obj.at("bids") << "\n";
}
}
}
Для input.txt:
[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": 111529187623,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:30.137] [exchange_fools] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212351,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187625,"prev_seq_num": 111529187624,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:31.137] [exchange_pools] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212352,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187626,"prev_seq_num": 111529187625,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:32.137] [exchange_mules] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212353,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187627,"prev_seq_num": 111529187626,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:33.137] [exchange_rulez] [info] Put Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212354,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187628,"prev_seq_num": 111529187627,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:34.137] [exchange_bools] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212355,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187629,"prev_seq_num": 111529187628,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:35.137] [exchange_cools] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212356,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187630,"prev_seq_num": 111529187629,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:36.137] [exchange_solos] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212357,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187631,"prev_seq_num": 111529187630,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:37.137] [exchange_rolos] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212358,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187632,"prev_seq_num": 111529187631,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:38.137] [exchange_sucks] [info] Fudge Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212359,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187633,"prev_seq_num": 111529187632,"asks": [],"bids": [[11666.14, 6.752865]]}
[2020-08-23 19:19:39.137] [exchange_rocks] [info] Get Object: {"type": "update","symbol": "BTC_USDT_20l","event_id": 1598210353212360,"event_time": 1598210365978240,"exchange_time": 1598210365818,"seq_num": 111529187634,"prev_seq_num": 111529187633,"asks": [],"bids": [[11666.14, 6.752865]]}
Выводит ожидаемый результат:
-----
Level: info
Time: 2020-08-23 19:19:29.137
Source: exchange_tools
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:30.137
Source: exchange_fools
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:31.137
Source: exchange_pools
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:32.137
Source: exchange_mules
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:34.137
Source: exchange_bools
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:35.137
Source: exchange_cools
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:36.137
Source: exchange_solos
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:37.137
Source: exchange_rolos
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
-----
Level: info
Time: 2020-08-23 19:19:39.137
Source: exchange_rocks
Type: "update"
Event Time: 1598210365978240
Asks: []
Bids: [[1.166614E4,6.752865E0]]
Много места для улучшения производительности. Я только что понял, что вы можете использовать Interprocess для карты памяти без привязки Iostreams: coliru.stacked-crooked.com/a/d4087995fd95c5bf Поскольку производительность сейчас действительно не актуальна, вы можете обойтись без Boost Iostreams для сопоставленного файла: coliru. stacked-crooked.com/a/58bad83959a2640a — идя в другую сторону, избегайте аллокации при разборе: coliru.stacked-crooked.com/a/0462e9ef42a93767
большое спасибо, я буду использовать этот образец для отправки запросов и ставок в std::map;
@JaMiT Сначала я так и думал, но потом мне пришла в голову идея сделать «шаблон» строки в регулярном выражении. Возможно, это упростило бы поиск. Но я думаю да, проще всего удалить первые символы с помощью стирания, спасибо!