MySources/csvfile.hpp

134 lines
3.6 KiB
C++
Executable File

#ifndef CSVFILE_HPP
#define CSVFILE_HPP
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
class csvFile;
inline static csvFile &endrow(csvFile &file);
inline static csvFile &flush(csvFile &file);
class csvFile {
std::ofstream fs_;
bool is_first_;
const std::string separator_;
const std::string escape_seq_;
const std::string special_chars_;
public:
csvFile(const std::filesystem::path &filename,
const bool &overwrite,
const std::string separator = ",")
: fs_(), is_first_(true), separator_(separator), escape_seq_("\""), special_chars_("\"")
{
fs_.exceptions(std::ios::failbit | std::ios::badbit);
if (filename.empty()) {
fs_.copyfmt(std::cout);
fs_.clear(std::cout.rdstate());
fs_.basic_ios<char>::rdbuf(std::cout.rdbuf());
} else {
if (!std::filesystem::exists(filename)) {
std::ofstream outfile(filename);
outfile.close();
}
overwrite ? fs_.open(filename, std::ios::trunc) : fs_.open(filename, std::ios::app);
}
}
~csvFile() {
flush();
fs_.close();
}
void flush() { fs_.flush(); }
void endrow() {
fs_ << std::endl;
is_first_ = true;
}
csvFile &operator<<(csvFile &(*val)(csvFile &)) { return val(*this); }
csvFile &operator<<(const char *val) { return write(escape(val)); }
csvFile &operator<<(const std::string &val) { return write(escape(val)); }
template<typename T>
csvFile &operator<<(const T &val)
{
return write(val);
}
static std::vector<std::vector<std::string>> parse(const std::filesystem::path &csvFilepath)
{
std::vector<std::vector<std::string>> resultCSV;
if (!std::filesystem::exists(csvFilepath)) {
std::cerr << "The file does not exist:" << csvFilepath.string() << std::endl;
return resultCSV;
}
std::ifstream inputfile(csvFilepath.string().c_str());
if (!inputfile.is_open()) {
std::cerr << "Can't open file:" << csvFilepath.string() << std::endl;
return resultCSV;
}
std::vector<std::string> row;
std::string line;
using Tokenizer = boost::tokenizer<boost::escaped_list_separator<char>>;
while (std::getline(inputfile, line)) {
Tokenizer tokenizer(line);
const int numOfCols = std::distance(tokenizer.begin(), tokenizer.end());
row.resize(numOfCols);
std::copy(tokenizer.begin(), tokenizer.end(), row.begin());
// std::transform(tokenizer.begin(), tokenizer.end(), row.begin(), [](const std::string &el) {
// return boost::lexical_cast<T>(el);
// });
resultCSV.push_back(row);
}
return resultCSV;
}
private:
template <typename T> csvFile &write(const T &val) {
if (!is_first_) {
fs_ << separator_;
} else {
is_first_ = false;
}
fs_ << val;
return *this;
}
std::string escape(const std::string &val) {
std::ostringstream result;
result << '"';
std::string::size_type to, from = 0u, len = val.length();
while (from < len && std::string::npos !=
(to = val.find_first_of(special_chars_, from))) {
result << val.substr(from, to - from) << escape_seq_ << val[to];
from = to + 1;
}
result << val.substr(from) << '"';
return result.str();
}
};
inline static csvFile &endrow(csvFile &file) {
file.endrow();
return file;
}
inline static csvFile &flush(csvFile &file) {
file.flush();
return file;
}
#endif // CSVFILE_HPP