C++ CSV parser – Reaching for perfection
Digging down into split_iterators and failing to combine these with istream_iterators I took one step back and ended up with a piece of code that I think is both clear and efficient. Look at this:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
template<class T>
std::vector<std::vector<T>> ParseCsv(std::istream& is)
{
using namespace std;
using namespace boost;
typedef iterator_range<string::iterator> range_t;
vector<vector<T>> result;
string row;
while(getline(is, row))
{
result.push_back(vector<T>());
vector<range_t> values;
split(values, row, is_any_of(","), token_compress_on);
transform(values.begin(), values.end(), back_inserter(result.back()), [](range_t& r) {
return boost::lexical_cast<T>(std::string(r.begin(), r.end()));
});
}
return result;
}
Usage:
vector<vector<int>> result = ParseCsv<int>(ifstream("test.csv"));
Nice. Seems like boost is essential nowadays for C++ programming. Can’t live without it.