您的位置:首页 > 编程语言 > C语言/C++

【C++】读写CSV文件

2017-02-08 14:44 537 查看
github:https://github.com/MyBoon/CSVparser

新建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();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: