#pragma once #include // std::filesystem::path #include // std::ofstream|ifstream #include // std::scientifc|setprecision #include // std::cout|endl #include // std::numeric_limits #include // std::istringstream #include // std::string #include // std::vector namespace iue::io { /// @brief Writes a numeric values to a file using a csv-format /// @param filepath file to be written including the desired extension /// @param table table with the rows to be written /// @param del delimiter between individual values /// @param header informative comment in the output file /// @param comments character signalling that a line is a comment (if used as first character of the line ) inline void savetxt(std::filesystem::path filepath, const std::vector>& table, char del = ' ', std::string header = "", char comments = '#') { // setup row writer callable auto serialize = [&del](const std::vector& row) -> std::string { std::ostringstream oss; for (auto iter = row.begin(); iter != std::prev(row.end()); ++iter) oss << std::scientific << std::setprecision(18) << *iter << del; oss << std::scientific << std::setprecision(18) << *std::prev(row.end()); // avoid trailing return oss << std::endl; return oss.str(); }; // check if data is present if (table.empty()) return; // open file std::ofstream stream; stream.exceptions(std::ifstream::badbit); stream.open(filepath); // write header lines if (!header.empty()) { std::string line; std::istringstream iss(header); while (std::getline(iss, line)) { stream << comments << ' ' << line << std::endl; } } // write data for (const auto& row : table) stream << serialize(row); } /// @brief Read numeric values stored in a csv-format /// @param filepath input file containing the numeric values /// @param del delimiter between individual values /// @param comments character signalling that a line is a comment (if used as first character of the line ) /// @return table which was read inline std::vector> loadtxt(std::filesystem::path filepath, char del = ' ', char comments = '#') { // setup row parser callable auto deserialize = [&del](const std::string& line) -> std::vector { std::vector res; std::stringstream stream(line); std::string item; while (std::getline(stream, item, del)) { std::stringstream ss(item); ss.exceptions(std::ios::failbit); auto value = std::numeric_limits::quiet_NaN(); ss >> value; res.push_back(value); } return res; }; // setup table std::vector> table; // open file std::ifstream stream; stream.exceptions(std::ifstream::badbit); stream.open(filepath); // read from stream row-by-row std::string line; // read line to row vectors while (std::getline(stream, line)) { if (line.front() == comments) continue; table.push_back(deserialize(line)); } return table; } } // namespace iue::io