#include #include "CsvFile.h" void CsvFile::ParseRow(std::string &line, std::vector &row, bool resize) { std::string entry, qbuf; bool isQuoted = false; int i = 0; if (resize) { row.clear(); } std::stringstream line_s(line); while (std::getline(line_s, entry, ',')) { if (!isQuoted && entry[0] == '"') { isQuoted = true; entry = entry.substr(1); } if (isQuoted) { if (entry[entry.size() - 1] == '"') { isQuoted = false; entry = entry.substr(0, entry.size() - 1); } qbuf += entry; if (!isQuoted) { if (resize) { row.push_back(qbuf); } else { row[i++] = qbuf; } qbuf.clear(); } } else { if (resize) { row.push_back(entry); } else { row[i++] = entry; } } } assert(!isQuoted); } void CsvFile::FromFile(const fs::path &filename, bool has_header) { std::ifstream handle(filename); std::string line; std::vector firstRow; for (_nrow = 0; std::getline(handle, line); _nrow++) { if (firstRow.empty()) { ParseRow(line, firstRow); _ncol = firstRow.size(); _colnames.resize(_ncol); } } handle.clear(); handle.seekg(0); if (has_header) { std::getline(handle, line); ParseRow(line, _colnames, false); _nrow--; } else { int i = 1; for (std::string & name : _colnames) { name = "V" + std::to_string(i++); } } _rows.resize(_nrow); for (auto & vec : _rows) { vec.resize(_ncol); std::getline(handle, line); ParseRow(line, vec, false); } } bool CsvFile::GetRow(size_t i, std::vector &row) const { if (i >= _nrow) { row.clear(); return false; } else { row = _rows[i]; return true; } } bool CsvFile::GetCol(size_t i, std::vector &col) const { if (i >= _ncol) { col.clear(); return false; } else { int j = 0; for (const auto & row : _rows) { col[j++] = row[i]; } return true; } } bool CsvFile::GetCol(const std::string &name, std::vector &col) const { auto it = std::find(_colnames.cbegin(), _colnames.cend(), name); if (it != _colnames.cend()) { size_t i = it - _colnames.cbegin(); return GetCol(i, col); } else { col.clear(); return false; } } bool CsvFile::GetCell(size_t row, size_t col, std::string &cell) const { if (row >= _nrow || col >= _ncol) { cell.clear(); return false; } else { cell = _rows[row][col]; return true; } } bool CsvFile::GetCell(const std::string &colname, size_t row, std::string &cell) const { auto it = std::find(_colnames.cbegin(), _colnames.cend(), colname); if (it != _colnames.cend()) { size_t i = it - _colnames.cbegin(); return GetCell(row, i, cell); } else { cell.clear(); return false; } } bool CsvFile::SetRow(size_t i, const std::vector &row) { if (i >= _nrow) { return false; } else { _rows[i] = row; return true; } } bool CsvFile::SetCol(size_t i, const std::vector &col) { if (i >= _ncol) { return false; } else { int j = 0; for (auto & row : _rows) { row[i] = col[j++]; } return true; } } bool CsvFile::SetCol(const std::string &name, const std::vector &col) { auto it = std::find(_colnames.cbegin(), _colnames.cend(), name); if (it != _colnames.cend()) { size_t i = it - _colnames.cbegin(); return SetCol(i, col); } else { return false; } } bool CsvFile::SetCell(size_t row, size_t col, const std::string &cell) { if (row >= _nrow || col >= _ncol) { return false; } else { _rows[row][col] = cell; return true; } } bool CsvFile::SetCell(const std::string &colname, size_t row, const std::string &cell) { auto it = std::find(_colnames.cbegin(), _colnames.cend(), colname); if (it != _colnames.cend()) { size_t i = it - _colnames.cbegin(); return SetCell(row, i, cell); } else { return false; } } void CsvFile::WriteRow(std::ofstream &ofile, const std::vector &row) { bool first = true; for (const auto & entry : row) { if (!first) { ofile << ','; } else { first = false; } bool has_comma = (entry.find(',') != std::string::npos); if (has_comma) { ofile << '"'; } ofile << entry; if (has_comma) { ofile << '"'; } } ofile << '\n'; } void CsvFile::ToFile(const fs::path &filename, bool write_header) { std::ofstream ofile(filename); if (write_header) { WriteRow(ofile, _colnames); } for (auto const & row : _rows) { WriteRow(ofile, row); } }