/
Vladimir_Solo
/
RZA_LAB
Обзор
Документация
Войти
/
Vladimir_Solo
/
RZA_LAB
Код
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
ExLabLibs/ParserComtrade.cpp
118 строк
4 KB
Федотов Руслан
LR3
05 май 2026, 15:38
05 май 2026, 15:38
74bfc5a
Код
Авторство
О чём код?
#include "ParserComtrade.h" #include "include.h" #include <fstream> #include <sstream> #include <stdexcept> #include <cctype> #include <algorithm> #include <cstdint> // Вспомогательная функция для очистки строк от мусора и пробелов string trimLine(const string& s) { string res = s; res.erase(remove(res.begin(), res.end(), '\r'), res.end()); res.erase(remove(res.begin(), res.end(), '\n'), res.end()); size_t first = res.find_first_not_of(" \t"); if (string::npos == first) return res; size_t last = res.find_last_not_of(" \t"); return res.substr(first, (last - first + 1)); } ParserComtrade::ParserComtrade(const string& cfg_file_, const string& dat_file_) : cfg_file(cfg_file_), dat_file(dat_file_), total_samples(0) { ifstream cfg(cfg_file); if (!cfg.is_open()) throw runtime_error("Could not open CFG file: " + cfg_file); string line, tmp; getline(cfg, line); // 1-я строка: Название станции getline(cfg, line); // 2-я строка: Кол-во каналов (напр. 4,3A,1D) stringstream ss_count(line); getline(ss_count, tmp, ','); int total_all = stoi(trimLine(tmp)); getline(ss_count, tmp, ','); int count_A = stoi(trimLine(tmp)); getline(ss_count, tmp, ','); int count_D = stoi(trimLine(tmp)); // Читаем аналоговые каналы for (int i = 0; i < total_all; ++i) { getline(cfg, line); if (i < count_A) { stringstream ss(line); vector<string> tokens; while (getline(ss, tmp, ',')) tokens.push_back(trimLine(tmp)); if (tokens.size() >= 7) { AnalogChannel ch; ch.index = stoi(tokens[0]); ch.name = tokens[1]; ch.unit = tokens[4]; // Юниты обычно в 5-й колонке ch.a = stod(tokens[5]); ch.b = stod(tokens[6]); analogChannels.push_back(ch); } } } // Пропускаем ненужные для базового парсинга строки (частота, выборки) getline(cfg, line); // f getline(cfg, line); // n rates int n_rates = stoi(trimLine(line)); for (int i = 0; i < n_rates; ++i) getline(cfg, line); getline(cfg, line); // Start time getline(cfg, line); // End time // Определяем формат (ASCII или BINARY) getline(cfg, line); string format = trimLine(line); transform(format.begin(), format.end(), format.begin(), ::toupper); analogData.resize(analogChannels.size()); // --- ЧТЕНИЕ ДАННЫХ --- if (format.find("BINARY") != string::npos) { ifstream dat(dat_file, ios::binary); if (!dat.is_open()) throw runtime_error("Could not open DAT file"); int digital_words = (count_D + 15) / 16; while (dat.peek() != EOF) { int32_t sample_idx, timestamp; if (!dat.read(reinterpret_cast<char*>(&sample_idx), 4)) break; if (!dat.read(reinterpret_cast<char*>(×tamp), 4)) break; timeData.push_back(static_cast<double>(timestamp) / 1000000.0); for (size_t i = 0; i < analogChannels.size(); ++i) { int16_t raw_val; // Стандартный BINARY использует 16-бит dat.read(reinterpret_cast<char*>(&raw_val), 2); double real_val = (static_cast<double>(raw_val) * analogChannels[i].a) + analogChannels[i].b; analogData[i].push_back(real_val); } dat.seekg(digital_words * 2, ios::cur); // Пропуск дискретов total_samples++; } } else { ifstream dat(dat_file); if (!dat.is_open()) throw runtime_error("Could not open DAT file"); while (getline(dat, line)) { line = trimLine(line); if (line.empty()) continue; stringstream ss(line); getline(ss, tmp, ','); // Номер getline(ss, tmp, ','); // Время if (!tmp.empty()) timeData.push_back(stod(tmp) / 1000000.0); for (size_t i = 0; i < analogChannels.size(); ++i) { if (getline(ss, tmp, ',')) { double raw = stod(tmp); analogData[i].push_back(raw * analogChannels[i].a + analogChannels[i].b); } } total_samples++; } } }