【C++】读写CSV文件
2017-02-08 14:44
537 查看
github:https://github.com/MyBoon/CSVparser
新建CSV文件:建txt——另存(UTF-8)——后缀.csv
CSVparser.hpp
CSVparser.cpp
Example:
插入与删除:
std::vector<std::string> myrow;
myrow.push_back("T");
myrow.push_back("A");
myrow.push_back("I");
file.deleteRow(1);
file.sync();
file.addRow(1, myrow);
file.sync();
新建CSV文件:建txt——另存(UTF-8)——后缀.csv
CSVparser.hpp
#ifndef _CSVPARSER_HPP_ # define _CSVPARSER_HPP_ # include <stdexcept> # include <string> # include <vector> # include <list> # include <sstream> namespace csv { class Error : public std::runtime_error { public: Error(const std::string &msg): std::runtime_error(std::string("CSVparser : ").append(msg)) { } }; class Row { public: Row(const std::vector<std::string> &); ~Row(void); public: unsigned int size(void) const; void push(const std::string &); bool set(const std::string &, const std::string &); private: const std::vector<std::string> _header; std::vector<std::string> _values; public: template<typename T> const T getValue(unsigned int pos) const { if (pos < _values.size()) { T res; std::stringstream ss; ss << _values[pos]; ss >> res; return res; } throw Error("can't return this value (doesn't exist)"); } const std::string operator[](unsigned int) const; const std::string operator[](const std::string &valueName) const; friend std::ostream& operator<<(std::ostream& os, const Row &row); friend std::ofstream& operator<<(std::ofstream& os, const Row &row); }; enum DataType { eFILE = 0, ePURE = 1 }; class Parser { public: Parser(const std::string &, const DataType &type = eFILE, char sep = ','); ~Parser(void); public: Row &getRow(unsigned int row) const; unsigned int rowCount(void) const; unsigned int columnCount(void) const; std::vector<std::string> getHeader(void) const; const std::string getHeaderElement(unsigned int pos) const; const std::string &getFileName(void) const; public: bool deleteRow(unsigned int row); bool addRow(unsigned int pos, const std::vector<std::string> &); void sync(void) const; protected: void parseHeader(void); void parseContent(void); private: std::string _file; const DataType _type; const char _sep; std::vector<std::string> _originalFile; std::vector<std::string> _header; std::vector<Row *> _content; public: Row &operator[](unsigned int row) const; }; } #endif /*!_CSVPARSER_HPP_*/
CSVparser.cpp
#include "stdafx.h" #include <fstream> #include <sstream> #include <iomanip> #include "CSVparser.hpp" namespace csv { Parser::Parser(const std::string &data, const DataType &type, char sep) : _type(type), _sep(sep) { std::string line; if (type == eFILE) { _file = data; std::ifstream ifile(_file.c_str()); if (ifile.is_open()) { while (ifile.good()) { getline(ifile, line); if (line != "") _originalFile.push_back(line); } ifile.close(); if (_originalFile.size() == 0) throw Error(std::string("No Data in ").append(_file)); parseHeader(); parseContent(); } else throw Error(std::string("Failed to open ").append(_file)); } else { std::istringstream stream(data); while (std::getline(stream, line)) if (line != "") _originalFile.push_back(line); if (_originalFile.size() == 0) throw Error(std::string("No Data in pure content")); parseHeader(); parseContent(); } } Parser::~Parser(void) { std::vector<Row *>::iterator it; for (it = _content.begin(); it != _content.end(); it++) delete *it; } void Parser::parseHeader(void) { std::stringstream ss(_originalFile[0]); std::string item; while (std::getline(ss, item, _sep)) _header.push_back(item); } void Parser::parseContent(void) { std::vector<std::string>::iterator it; it = _originalFile.begin(); it++; // skip header for (; it != _originalFile.end(); it++) { bool quoted = false; int tokenStart = 0; unsigned int i = 0; Row *row = new Row(_header); for (; i != it->length(); i++) { if (it->at(i) == '"') quoted = ((quoted) ? (false) : (true)); else if (it->at(i) == ',' && !quoted) { row->push(it->substr(tokenStart, i - tokenStart)); tokenStart = i + 1; } } //end row->push(it->substr(tokenStart, it->length() - tokenStart)); // if value(s) missing if (row->size() != _header.size()) throw Error("corrupted data !"); _content.push_back(row); } } Row &Parser::getRow(unsigned int rowPosition) const { if (rowPosition < _content.size()) return *(_content[rowPosition]); throw Error("can't return this row (doesn't exist)"); } Row &Parser::operator[](unsigned int rowPosition) const { return Parser::getRow(rowPosition); } unsigned int Parser::rowCount(void) const { return _content.size(); } unsigned int Parser::columnCount(void) const { return _header.size(); } std::vector<std::string> Parser::getHeader(void) const { return _header; } const std::string Parser::getHeaderElement(unsigned int pos) const { if (pos >= _header.size()) throw Error("can't return this header (doesn't exist)"); return _header[pos]; } bool Parser::deleteRow(unsigned int pos) { if (pos < _content.size()) { delete *(_content.begin() + pos); _content.erase(_content.begin() + pos); return true; } return false; } bool Parser::addRow(unsigned int pos, const std::vector<std::string> &r) { Row *row = new Row(_header); for (auto it = r.begin(); it != r.end(); it++) row->push(*it); if (pos <= _content.size()) { _content.insert(_content.begin() + pos, row); return true; } return false; } void Parser::sync(void) const { if (_type == DataType::eFILE) { std::ofstream f; f.open(_file, std::ios::out | std::ios::trunc); // header unsigned int i = 0; for (auto it = _header.begin(); it != _header.end(); it++) { f << *it; if (i < _header.size() - 1) f << ","; else f << std::endl; i++; } for (auto it = _content.begin(); it != _content.end(); it++) f << **it << std::endl; f.close(); } } const std::string &Parser::getFileName(void) const { return _file; } /* ** ROW */ Row::Row(const std::vector<std::string> &header) : _header(header) {} Row::~Row(void) {} unsigned int Row::size(void) const { return _values.size(); } void Row::push(const std::string &value) { _values.push_back(value); } bool Row::set(const std::string &key, const std::string &value) { std::vector<std::string>::const_iterator it; int pos = 0; for (it = _header.begin(); it != _header.end(); it++) { if (key == *it) { _values[pos] = value; return true; } pos++; } return false; } const std::string Row::operator[](unsigned int valuePosition) const { if (valuePosition < _values.size()) return _values[valuePosition]; throw Error("can't return this value (doesn't exist)"); } const std::string Row::operator[](const std::string &key) const { std::vector<std::string>::const_iterator it; int pos = 0; for (it = _header.begin(); it != _header.end(); it++) { if (key == *it) return _values[pos]; pos++; } throw Error("can't return this value (doesn't exist)"); } std::ostream &operator<<(std::ostream &os, const Row &row) { for (unsigned int i = 0; i != row._values.size(); i++) os << row._values[i] << " | "; return os; } std::ofstream &operator<<(std::ofstream &os, const Row &row) { for (unsigned int i = 0; i != row._values.size(); i++) { os << row._values[i]; if (i < row._values.size() - 1) os << ","; } return os; } }
Example:
#include "stdafx.h" #include <iostream> #include "CsvWriter.h" #include "CSVparser.hpp" using namespace std; using namespace csv; int _tmain(int argc, _TCHAR* argv[]) { //Parser CSV(".\\files\\readme.csv"); //int row = CSV.rowCount(); //int col = CSV.columnCount(); //cout << "row:" << row << ", col:" << col << endl; //std::vector<std::string> head = CSV.getHeader(); //std::string str = CSV.getFileName(); //std::string headq[10]; // //for (int i = 0; i < head.size(); i++){ // headq[i] = CSV.getHeaderElement(i); //} try { csv::Parser file = csv::Parser("files/readme.csv"); std::cout << file[0][0] << std::endl; // display : 1997 std::cout << file[0] << std::endl; // display : 1997 | Ford | E350 std::cout << file[1]["Model"] << std::endl; // display : Cougar std::cout << file.rowCount() << std::endl; // display : 2 std::cout << file.columnCount() << std::endl; // display : 3 std::cout << file.getHeaderElement(2) << std::endl; // display : Model } catch (csv::Error &e) { std::cerr << e.what() << std::endl; } return 0; }
插入与删除:
std::vector<std::string> myrow;
myrow.push_back("T");
myrow.push_back("A");
myrow.push_back("I");
file.deleteRow(1);
file.sync();
file.addRow(1, myrow);
file.sync();