parsing - How can I read and parse CSV files in C++? -
i need load , use csv file data in c++. @ point can comma-delimited parser (ie don't worry escaping new lines , commas). main need line-by-line parser return vector next line each time method called.
i found article looks quite promising: http://www.boost.org/doc/libs/1_35_0/libs/spirit/example/fundamental/list_parser.cpp
i've never used boost's spirit, willing try it. if there isn't more straightforward solution i'm overlooking.
if don't care escaping comma , newline,
, can't embed comma , newline in quotes (if can't escape then...)
3 lines of code (ok 14 ->but 15 read whole file).
std::vector<std::string> getnextlineandsplitintotokens(std::istream& str) { std::vector<std::string> result; std::string line; std::getline(str,line); std::stringstream linestream(line); std::string cell; while(std::getline(linestream,cell, ',')) { result.push_back(cell); } // checks trailing comma no data after it. if (!linestream && cell.empty()) { // if there trailing comma add empty element. result.push_back(""); } return result; }
i create class representing row.
stream object:
#include <iterator> #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <string> class csvrow { public: std::string const& operator[](std::size_t index) const { return m_data[index]; } std::size_t size() const { return m_data.size(); } void readnextrow(std::istream& str) { std::string line; std::getline(str, line); std::stringstream linestream(line); std::string cell; m_data.clear(); while(std::getline(linestream, cell, ',')) { m_data.push_back(cell); } // checks trailing comma no data after it. if (!linestream && cell.empty()) { // if there trailing comma add empty element. m_data.push_back(""); } } private: std::vector<std::string> m_data; }; std::istream& operator>>(std::istream& str, csvrow& data) { data.readnextrow(str); return str; } int main() { std::ifstream file("plop.csv"); csvrow row; while(file >> row) { std::cout << "4th element(" << row[3] << ")\n"; } }
but little work technically create iterator:
class csviterator { public: typedef std::input_iterator_tag iterator_category; typedef csvrow value_type; typedef std::size_t difference_type; typedef csvrow* pointer; typedef csvrow& reference; csviterator(std::istream& str) :m_str(str.good()?&str:null) { ++(*this); } csviterator() :m_str(null) {} // pre increment csviterator& operator++() {if (m_str) { if (!((*m_str) >> m_row)){m_str = null;}}return *this;} // post increment csviterator operator++(int) {csviterator tmp(*this);++(*this);return tmp;} csvrow const& operator*() const {return m_row;} csvrow const* operator->() const {return &m_row;} bool operator==(csviterator const& rhs) {return ((this == &rhs) || ((this->m_str == null) && (rhs.m_str == null)));} bool operator!=(csviterator const& rhs) {return !((*this) == rhs);} private: std::istream* m_str; csvrow m_row; }; int main() { std::ifstream file("plop.csv"); for(csviterator loop(file); loop != csviterator(); ++loop) { std::cout << "4th element(" << (*loop)[3] << ")\n"; } }
Comments
Post a Comment