C++11:借助std::tuple实现CSV的读写

时间:2023-02-07 00:31:07

一直想写个CSV读写的模板,但是接口的定义一直是个问题。CSV每列都可以任意映射成C++基本类型,怎么把接口定义得既通用又灵活?最近发现C++11引入了tuple,接口也可以像python一样的方便漂亮,而且不再依赖boost库,真正做到Windows/Linux一套代码。


#ifndef _CSV_TO_TUPLES_H
#define _CSV_TO_TUPLES_H

#include <stdlib.h>
#include <string>
#include <istream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <memory>
#include "common/common_utils.h"

namespace util {
namespace csv_tuple {


template <typename T>
class NullType
{
public:
explicit NullType()
: is_null(true) // by default, NULL value
{}

explicit NullType(const NullType& src)
: is_null(src.is_null), value(src.value)
{}

explicit NullType(const T& v)
: is_null(false), value(v)
{}

~NullType()
{}

void Reset()
{
// not all types can be reset by assigning of 0
*this = NullType();
}

NullType& operator=(const NullType& src)
{
this->is_null = src.is_null;
this->value = src.value;
return *this;
}

public:
bool is_null;
T value;
};

typedef NullType<char> NullChar;
typedef NullType<unsigned char> NullUChar;
typedef NullType<short> NullShort;
typedef NullType<unsigned short> NullUShort;
typedef NullType<int> NullInt;
typedef NullType<unsigned int> NullUInt;
typedef NullType<long long> NullBigInt;
typedef NullType<unsigned long long> NullUBigInt;
typedef NullType<float> NullFloat;
typedef NullType<float> NullReal;
typedef NullType<double> NullDouble;

typedef NullType<bool> NullBool;
typedef NullType<std::string> NullString;


template <typename T>
void StringToValue(const std::string& str, NullType<T>& value)
{
if (str.empty()) {
value.Reset();
}
else {
value.is_null = false;
StringToValue(str, value.value);
}
}

static inline void StringToValue(const std::string &str, char &value)
{
value = (char)atoi(str.c_str());
}

static inline void StringToValue(const std::string &str, unsigned char &value)
{
value = (unsigned char)atoi(str.c_str());
}

static inline void StringToValue(const std::string &str, short &value)
{
value = (short)atoi(str.c_str());
}

static inline void StringToValue(const std::string &str, unsigned short &value)
{
value = (unsigned short)atoi(str.c_str());
}

static inline void StringToValue(const std::string &str, int &value)
{
value = atoi(str.c_str());
}

static inline void StringToValue(const std::string &str, unsigned int &value)
{
value = (unsigned int)std::strtoul(str.c_str(), NULL, 10);
}

static inline void StringToValue(const std::string &str, long long &value)
{
#ifdef _WIN32
value = _atoi64(str.c_str());
#else
value = atoll(str.c_str());
#endif
}

static inline void StringToValue(const std::string &str, unsigned long long &value)
{
value = (unsigned long long)std::strtoull(str.c_str(), NULL, 10);
}

static inline void StringToValue(const std::string &str, bool &value)
{
value = atoi(str.c_str()) != 0;
}

static inline void StringToValue(const std::string& str, std::string& value)
{
value = str;
}

static inline void StringToValue(const std::string& str, float& value)
{
value = (float)atof(str.c_str());
}

static inline void StringToValue(const std::string& str, double& value)
{
value = atof(str.c_str());
}

// add more versions of StringToValue() if needed


#define TUPLE_SET_ITEM(tp, i) \
T##i t##i; \
StringToValue(subs[i], t##i); \
std::get<i>(tp) = t##i

template<typename T0>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0>& tp)
{
TUPLE_SET_ITEM(tp, 0);
}

template<typename T0, typename T1>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
}

template<typename T0, typename T1, typename T2>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
}

template<typename T0, typename T1, typename T2, typename T3>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
TUPLE_SET_ITEM(tp, 8);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
TUPLE_SET_ITEM(tp, 8);
TUPLE_SET_ITEM(tp, 9);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
TUPLE_SET_ITEM(tp, 8);
TUPLE_SET_ITEM(tp, 9);
TUPLE_SET_ITEM(tp, 10);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
TUPLE_SET_ITEM(tp, 8);
TUPLE_SET_ITEM(tp, 9);
TUPLE_SET_ITEM(tp, 10);
TUPLE_SET_ITEM(tp, 11);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10, typename T11,
typename T12>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
TUPLE_SET_ITEM(tp, 8);
TUPLE_SET_ITEM(tp, 9);
TUPLE_SET_ITEM(tp, 10);
TUPLE_SET_ITEM(tp, 11);
TUPLE_SET_ITEM(tp, 12);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10, typename T11,
typename T12, typename T13>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
TUPLE_SET_ITEM(tp, 8);
TUPLE_SET_ITEM(tp, 9);
TUPLE_SET_ITEM(tp, 10);
TUPLE_SET_ITEM(tp, 11);
TUPLE_SET_ITEM(tp, 12);
TUPLE_SET_ITEM(tp, 13);
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10, typename T11,
typename T12, typename T13, typename T14>
void FillTuple(const std::vector<std::string>& subs,
std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>& tp)
{
TUPLE_SET_ITEM(tp, 0);
TUPLE_SET_ITEM(tp, 1);
TUPLE_SET_ITEM(tp, 2);
TUPLE_SET_ITEM(tp, 3);
TUPLE_SET_ITEM(tp, 4);
TUPLE_SET_ITEM(tp, 5);
TUPLE_SET_ITEM(tp, 6);
TUPLE_SET_ITEM(tp, 7);
TUPLE_SET_ITEM(tp, 8);
TUPLE_SET_ITEM(tp, 9);
TUPLE_SET_ITEM(tp, 10);
TUPLE_SET_ITEM(tp, 11);
TUPLE_SET_ITEM(tp, 12);
TUPLE_SET_ITEM(tp, 13);
TUPLE_SET_ITEM(tp, 14);
}

// add more versions of FillTuple() if needed

#undef TUPLE_SET_ITEM


template <typename T>
static inline std::string ValueToStr(const T& value)
{
std::stringstream ss;
ss << value;
std::string str;
ss >> str;
return str;
}

template <>
std::string ValueToStr(const double& value)
{
std::stringstream ss;
ss << std::setprecision(11) << value;
std::string str;
ss >> str;
return str;
}

template <>
std::string ValueToStr(const float& value)
{
std::stringstream ss;
ss << std::setprecision(11) << value;
std::string str;
ss >> str;
return str;
}

template <>
std::string ValueToStr(const std::string& value)
{
std::string ret("\"");
ret += value;
ret += '\"';
return std::move(ret);
}

template<typename T0>
void FillLine(const std::tuple<T0>& tp, char /*delimiter*/, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
}

template<typename T0, typename T1>
void FillLine(const std::tuple<T0, T1>& tp, char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
}

template<typename T0, typename T1, typename T2>
void FillLine(const std::tuple<T0, T1, T2>& tp, char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
}

template<typename T0, typename T1, typename T2, typename T3>
void FillLine(const std::tuple<T0, T1, T2, T3>& tp, char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4>
void FillLine(const std::tuple<T0, T1, T2, T3, T4>& tp, char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5>& tp, char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6>& tp, char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7>& tp, char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7, typename T8>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>& tp,
char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
line += delimiter;
line += ValueToStr(std::get<8>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7, typename T8, typename T9>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& tp,
char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
line += delimiter;
line += ValueToStr(std::get<8>(tp));
line += delimiter;
line += ValueToStr(std::get<9>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7, typename T8, typename T9, typename T10>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& tp,
char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
line += delimiter;
line += ValueToStr(std::get<8>(tp));
line += delimiter;
line += ValueToStr(std::get<9>(tp));
line += delimiter;
line += ValueToStr(std::get<10>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7, typename T8, typename T9, typename T10, typename T11>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>& tp,
char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
line += delimiter;
line += ValueToStr(std::get<8>(tp));
line += delimiter;
line += ValueToStr(std::get<9>(tp));
line += delimiter;
line += ValueToStr(std::get<10>(tp));
line += delimiter;
line += ValueToStr(std::get<11>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>& tp,
char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
line += delimiter;
line += ValueToStr(std::get<8>(tp));
line += delimiter;
line += ValueToStr(std::get<9>(tp));
line += delimiter;
line += ValueToStr(std::get<10>(tp));
line += delimiter;
line += ValueToStr(std::get<11>(tp));
line += delimiter;
line += ValueToStr(std::get<12>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>& tp,
char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
line += delimiter;
line += ValueToStr(std::get<8>(tp));
line += delimiter;
line += ValueToStr(std::get<9>(tp));
line += delimiter;
line += ValueToStr(std::get<10>(tp));
line += delimiter;
line += ValueToStr(std::get<11>(tp));
line += delimiter;
line += ValueToStr(std::get<12>(tp));
line += delimiter;
line += ValueToStr(std::get<13>(tp));
}

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14>
void FillLine(const std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>& tp,
char delimiter, std::string& line)
{
line = ValueToStr(std::get<0>(tp));
line += delimiter;
line += ValueToStr(std::get<1>(tp));
line += delimiter;
line += ValueToStr(std::get<2>(tp));
line += delimiter;
line += ValueToStr(std::get<3>(tp));
line += delimiter;
line += ValueToStr(std::get<4>(tp));
line += delimiter;
line += ValueToStr(std::get<5>(tp));
line += delimiter;
line += ValueToStr(std::get<6>(tp));
line += delimiter;
line += ValueToStr(std::get<7>(tp));
line += delimiter;
line += ValueToStr(std::get<8>(tp));
line += delimiter;
line += ValueToStr(std::get<9>(tp));
line += delimiter;
line += ValueToStr(std::get<10>(tp));
line += delimiter;
line += ValueToStr(std::get<11>(tp));
line += delimiter;
line += ValueToStr(std::get<12>(tp));
line += delimiter;
line += ValueToStr(std::get<13>(tp));
line += delimiter;
line += ValueToStr(std::get<14>(tp));
}
}

template<typename... Args>
bool CsvToTuples(std::istream& in, char delimiter, std::vector<std::tuple<Args...> >& tuples,
std::string& err)
{
const size_t N = sizeof...(Args);
std::string line;
std::vector<std::string> subs;

std::tuple<Args...> tp;
while (util::GetLine(in, line)) {
if (line[0] == '#') { // ignore comment
continue;
}

util::ParseCsvLine(subs, line, delimiter);
if (subs.size() < N) {
std::ostringstream oss;
oss << "Error: unexpected column size. Expected: " << N << ", Actual: " << subs.size()
<< ", line data : " << line;
err = oss.str();
return false;
}

csv_tuple::FillTuple(subs, tp);
tuples.push_back(tp);
}

return true;
}

template<typename... Args>
bool CsvToTuples(const std::string& csv_pathname, char delimiter,
std::vector<std::tuple<Args...> >& tuples, std::string& err)
{
std::ifstream in(csv_pathname.c_str());
if (!in.good()) {
err = "Error in opening file \"" + csv_pathname + "\"";
return false;
}

return CsvToTuples(in, delimiter, tuples, err);
}

template<typename... Args>
bool TuplesToCsv(const std::string& head, std::vector<std::tuple<Args...> >& tuples,
std::ostream& out, char delimiter, std::string& err)
{
if (!head.empty()) {
out << head << std::endl;
}

const size_t N = sizeof...(Args);
std::string line;

const size_t buff_size = 1024 * 8;
std::string buff;
buff.reserve(buff_size + 256);

for (auto& t : tuples) {
csv_tuple::FillLine(t, delimiter, line);
buff += line;
buff += '\n';
if (buff.length() > buff_size) {
out << buff;
buff.clear();
}
}
if (!buff.empty()) {
out << buff;
}

return true;
}

template<typename... Args>
bool TuplesToCsv(const std::string& head, std::vector<std::tuple<Args...> >& tuples,
const std::string& csv_pathname, char delimiter, std::string& err)
{
std::ofstream out(csv_pathname.c_str());
if (!out.good()) {
err = "Error in opening file \"" + csv_pathname + "\"";
return false;
}

return TuplesToCsv(head, tuples, out, delimiter, err);
}

}

#endif //_CSV_TO_TUPLES_H



写文件调用示例。读文件的略。


    typedef std::tuple<std::string, std::string, double, int> out_entry;
std::vector<out_entry> tuples;
tuples.push_back(std::make_tuple("ABC", "", 100.1, 100));
std::string head("# COLUMN1,COLUMN2,COLUMN3,COLUMN4"), err;
TuplesToCsv(head, tuples, csv, ',' , err);