Created
December 23, 2015 18:33
-
-
Save koturn/04714109987b0d204326 to your computer and use it in GitHub Desktop.
Simple csv parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef CSV_PARSER_H | |
| #define CSV_PARSER_H | |
| /*! | |
| * @brief Simple csv parser | |
| * @author koturn | |
| * @date 2015 12/24 | |
| * @file CsvParser.h | |
| * @version 0.1 | |
| */ | |
| #include <fstream> | |
| #include <sstream> | |
| #include <string> | |
| #include <vector> | |
| #include <iostream> | |
| template<typename DlmType> | |
| static inline std::vector<std::string> | |
| split(std::string line, const DlmType &delimiter); | |
| /*! | |
| * @brief Simple csv parser | |
| */ | |
| class CsvParser { | |
| private: | |
| std::ifstream fileStream; | |
| public: | |
| CsvParser(void) : | |
| fileStream() | |
| {} | |
| CsvParser(const std::string &csvFilename) : | |
| fileStream(csvFilename.c_str()) | |
| {} | |
| CsvParser(const char *csvFilename) : | |
| fileStream(csvFilename) | |
| {} | |
| bool setFile(const std::string &csvFilename) | |
| { | |
| return setFile(csvFilename.c_str()); | |
| } | |
| bool setFile(const char *csvFilename) | |
| { | |
| fileStream.open(csvFilename); | |
| return !fileStream.fail(); | |
| } | |
| template<typename ElmType, typename DlmType> | |
| std::vector<std::vector<ElmType> > parseAll(const DlmType &delimiter); | |
| template<typename ElmType, typename DlmType> | |
| void _parseAll(std::vector<std::vector<ElmType> > &csvElms, const DlmType &delimiter); | |
| template<typename DlmType> | |
| std::vector<std::vector<std::string> > parseAll(const DlmType &delimiter); | |
| template<typename DlmType> | |
| void _parseAll(std::vector<std::vector<std::string> > &csvElms, const DlmType &delimiter); | |
| template<typename ElmType, typename DlmType, typename FuncType> | |
| std::vector<std::vector<ElmType> > parse(const DlmType &delimiter, const FuncType &operation); | |
| template<typename ContType, typename DlmType, typename FuncType> | |
| void _parse(ContType &container, const DlmType &delimiter, const FuncType &operation); | |
| }; // class CsvParser | |
| /*! | |
| * @brief Parse csv file | |
| * | |
| * @code | |
| * CsvParser cr("sample.csv"); | |
| * std::vector<std::vector<int> > vct = cr.parseAll<int>(','); | |
| * @endcode | |
| * | |
| * @tparam ElmType Type of csv-element | |
| * @tparam DlmType Type of delimiter (Assumption: std::string, const char *, char) | |
| * @param [in] delimiter Delimiter of csv file | |
| * | |
| * @return 2D vector of csv-elements (All element type is ElmType) | |
| */ | |
| template<typename ElmType, typename DlmType> | |
| std::vector<std::vector<ElmType> > | |
| CsvParser::parseAll(const DlmType &delimiter) | |
| { | |
| std::vector<std::vector<ElmType> > csvElms; | |
| _parseAll(csvElms, delimiter); | |
| return csvElms; | |
| } | |
| /*! | |
| * @brief Parse csv file (specialized for std::string) | |
| * | |
| * @code | |
| * CsvParser cr("sample.csv"); | |
| * std::vector<std::vector<std::string> > vct = cr.parseAll(','); | |
| * @endcode | |
| * | |
| * @tparam DlmType Type of delimiter (Assumption: std::string, const char *, char) | |
| * @param [in] delimiter Delimiter of csv file | |
| * | |
| * @return 2D vector of csv-elements (All element type is std::string) | |
| */ | |
| template<typename DlmType> | |
| std::vector<std::vector<std::string> > | |
| CsvParser::parseAll(const DlmType &delimiter) | |
| { | |
| std::vector<std::vector<std::string> > csvElms; | |
| _parseAll(csvElms, delimiter); | |
| return csvElms; | |
| } | |
| /*! | |
| * @brief Parse csv file | |
| * | |
| * @tparam ElmType Type of csv-element | |
| * @tparam DlmType Type of delimiter (Assumption: std::string, const char *, char) | |
| * @param [out] csvElms 2D vector to store csv-elements (All element type is ElmType) | |
| * @param [in] delimiter Delimiter of csv file | |
| */ | |
| template<typename ElmType, typename DlmType> | |
| void | |
| CsvParser::_parseAll( | |
| std::vector<std::vector<ElmType> > &csvElms, | |
| const DlmType &delimiter) | |
| { | |
| if (!fileStream) { | |
| throw "Bad stream"; | |
| } | |
| std::string line; | |
| std::stringstream ss; | |
| while (fileStream >> line) { | |
| std::vector<std::string> _lineElms = split(line, delimiter); | |
| std::vector<ElmType> lineElms(_lineElms.size()); | |
| int idx = 0; | |
| for (std::vector<std::string>::const_iterator itr = _lineElms.begin(); itr != _lineElms.end(); ++itr) { | |
| ss << *itr; | |
| ss >> lineElms[idx++]; | |
| ss.str(""); | |
| ss.clear(std::stringstream::goodbit); | |
| } | |
| csvElms.push_back(lineElms); | |
| } | |
| } | |
| /*! | |
| * @brief Parse csv file | |
| * | |
| * @tparam DlmType Type of delimiter (Assumption: std::string, const char *, char) | |
| * @param [out] csvElms 2D vector to store csv-elements (All element type is std::string) | |
| * @param [in] delimiter Delimiter of csv file | |
| */ | |
| template<typename DlmType> | |
| void | |
| CsvParser::_parseAll( | |
| std::vector<std::vector<std::string> > &csvElms, | |
| const DlmType &delimiter) | |
| { | |
| if (!fileStream) { | |
| throw "Bad stream"; | |
| } | |
| std::string line; | |
| while (fileStream >> line) { | |
| std::vector<std::string> lineElms = split(line, delimiter); | |
| csvElms.push_back(lineElms); | |
| } | |
| } | |
| /*! | |
| * @brief Parse csv file | |
| * | |
| * You can custamize reading action as second argument 'operation' | |
| * | |
| * @tparam ElmType Type of csv-element | |
| * @tparam DlmType Type of delimiter (Assumption: std::string, const char *, char) | |
| * @tparam FuncType Type of functional object (dummy) | |
| * @param [in] delimiter Delimiter of csv file | |
| * @param [in] operation Operation for one line in csv-file (Functional object) | |
| * | |
| * @return 2D vector of csv-elements (All element type is ElmType) | |
| */ | |
| template<typename ElmType, typename DlmType, typename FuncType> | |
| std::vector<std::vector<ElmType> > | |
| CsvParser::parse( | |
| const DlmType &delimiter, | |
| const FuncType &operation) | |
| { | |
| std::vector<std::vector<ElmType> > csvDatas; | |
| _parse(csvDatas, delimiter, operation); | |
| return csvDatas; | |
| } | |
| /*! | |
| * @brief Parse csv file | |
| * | |
| * You can custamize reading action as second argument 'operation' | |
| * | |
| * @code | |
| * #include <cstdlib> | |
| * #include <sstream> | |
| * #include <vector> | |
| * #include "CsvParser.h" | |
| * | |
| * struct CustomOperation | |
| * { | |
| * void operator()(std::vector<std::vector<double> > &container, const std::vector<std::string> &lineElms) const | |
| * { | |
| * std::stringstream ss; | |
| * std::vector<double> customLineElms; | |
| * for (std::vector<std::string>::const_iterator itr = lineElms.begin(); itr != lineElms.end(); ++itr) { | |
| * double e; | |
| * ss << *itr; | |
| * ss >> e; | |
| * ss.str(""); | |
| * ss.clear(std::stringstream::goodbit); | |
| * customLineElms.push_back(e); | |
| * } | |
| * container.push_back(customLineElms); | |
| * } | |
| * }; | |
| * | |
| * int | |
| * main(void) | |
| * { | |
| * CsvParser cr("sample.csv"); | |
| * std::vector<std::vector<double> > vct = cr.parse<double>(',', CustomOperation()); | |
| * // ... | |
| * return EXIT_SUCCESS; | |
| * } | |
| * @endcode | |
| * | |
| * @tparam ContType Type of element-container (for example, std::vector<std::vector<int> >) | |
| * @tparam DlmType Type of delimiter (Assumption: std::string, const char *, char) | |
| * @tparam FuncType Type of functional object (dummy) | |
| * @param [out] container element-container | |
| * @param [in] delimiter Delimiter of csv file | |
| * @param [in] operation Operation for one line in csv-file (Functional object) | |
| */ | |
| template<typename ContType, typename DlmType, typename FuncType> | |
| void | |
| CsvParser::_parse( | |
| ContType &container, | |
| const DlmType &delimiter, | |
| const FuncType &operation) | |
| { | |
| if (!fileStream) { | |
| throw "Bad stream"; | |
| } | |
| std::string line; | |
| while (fileStream >> line) { | |
| std::vector<std::string> lineElms = split(line, delimiter); | |
| operation(container, lineElms); | |
| } | |
| } | |
| /*! | |
| * @brief Split string by specified delimiter | |
| * @param [in] line One line | |
| * @param [in] delimiter Separate charactor or string | |
| * @return line-elements (as std::vector) | |
| */ | |
| template<typename DlmType> | |
| static inline std::vector<std::string> | |
| split(std::string line, const DlmType &delimiter) | |
| { | |
| std::vector<std::string> lineElms; | |
| int pos; | |
| while ((pos = line.find_first_of(delimiter)) != std::string::npos) { | |
| if (pos > 0) { | |
| lineElms.push_back(line.substr(0, pos)); | |
| } | |
| line = line.substr(pos + 1); | |
| } | |
| if (line.length() > 0) { | |
| lineElms.push_back(line); | |
| } | |
| return lineElms; | |
| } | |
| #endif // CSV_PARSER_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment