zoukankan      html  css  js  c++  java
  • CSV文件读取类

    最近项目中,经常需要读取Csv文件。基本步骤是:

    (1)按行读取

    (2)然后将一行数据按逗号,分割为字符串数组

    (3)将各列字符串转换成相应类型的数据 ,如int double类型

    写了一个简单的Csv文件读取类,方便使用,可以按列名或列索引读取数据。将字符串转换成数字变量使用的是stringstream类。

    如下:

    #ifndef CSV_READER_H_
    #define CSV_READER_H_
    #include <vector>
    #include <map>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <algorithm>
    
    using std::string;
    using std::vector;
    using std::map;
    using std::ifstream;
    using std::stringstream;
    
    class CsvReader
    {
    public:
    	//不区分大小写 比较字符串
    	struct NoCaseCompareStr
    	{
    		bool operator()(const string & str1, const string & str2)
    		{
    			string upper_str1(str1);
    			string upper_str2(str2);
    			std::transform(upper_str1.begin(),upper_str1.end(),upper_str1.begin(),toupper);
    			std::transform(upper_str2.begin(),upper_str2.end(),upper_str2.begin(),toupper);
    			return upper_str1.compare(upper_str2) >= 0 ? false : true;
    		}
    	};
    
    	typedef map<string,int,NoCaseCompareStr> ColumnIndexMap;
    
    	CsvReader();
    	virtual ~CsvReader();
    	//加载Csv文件
    	bool LoadFile(const string & fileName);
    	//读取一行数据
    	bool Read();
    	void Close();
    	//得到列名字段的索引
    	int GetColumnIndex(const string & columnName);
    	
    	//按列名索引读取
    	template<typename T>
    	bool GetValue(int columnIndex, T & val);
    
    	template<typename T>
    	T GetValue(int columnIndex);
    
    	//按列名提取数据
    	template<typename T>
    	bool GetValue(const string & columnName, T & val);
    
    	template<typename T>
    	T GetValue(const string & columnName);
    
    	//分割字符串为字符数组
    	static void SplitString(const string & str, vector<string> & str_vec, char delimiter);
    
    private:
    	ColumnIndexMap _columnIndex;	//字段所对应列的索引
    	vector<string> _lineData;//Csv文件一行数据
    	ifstream _fi;
    	bool _fileIsOpen;
    	string _line;
    	stringstream _ss;
    };
    
    template<typename T>
    T CsvReader::GetValue( const string & columnName )
    {
    	int columnIndex = this->GetColumnIndex(columnName);
    	return this->GetValue<T>(columnIndex);
    }
    
    template<typename T>
    bool CsvReader::GetValue( const string & columnName, T & val )
    {
    	int columnIndex = this->GetColumnIndex(columnName);
    	return this->GetValue(columnIndex,val);
    }
    
    template<typename T>
    T CsvReader::GetValue( int columnIndex )
    {
    	T val;
    	_ss.clear();
    	_ss.str("");
    	if (columnIndex < 0 || columnIndex >= (int)_lineData.size())
    	{
    		return T();
    	}
    	else
    	{
    		_ss.str(_lineData[columnIndex]);
    	}
    	_ss >> val;
    	return val;
    }
    
    template<typename T>
    bool CsvReader::GetValue( int columnIndex, T & val )
    {
    	if (columnIndex < 0 || columnIndex >= (int)_lineData.size())
    	{
    		return false;
    	}
    	_ss.str("");
    	_ss.clear();
    	_ss.str(_lineData[columnIndex]);
    	_ss >> val;
    	return true;
    }
    
    #endif

     cpp文件:

    #include "CsvReader.h"
    
    CsvReader::CsvReader()
    	: _fileIsOpen(false)
    {
    
    }
    
    CsvReader::~CsvReader()
    {
    	this->Close();
    }
    
    bool CsvReader::LoadFile( const string & fileName )
    {
    	if (_fileIsOpen)	//先关闭原来的文件
    	{
    		this->Close();
    	}
    	_fi.open(fileName);
    	if (!_fi.is_open())
    	{
    		return false;
    	}
    	_fileIsOpen = true;
    	//读取第一行数据,得到CSV文件各列字段名称,并生成索引
    	if (!this->Read())
    	{
    		return false;
    	}
    	int columnCount = _lineData.size();
    	for (int columnIndex = 0; columnIndex < columnCount; columnIndex++)
    	{
    		_columnIndex[_lineData[columnIndex]] = columnIndex;
    	}
    	return true;
    }
    
    void CsvReader::Close()
    {
    	_fi.close();
    	_lineData.clear();
    	_columnIndex.clear();
    	_fileIsOpen = false;
    }
    
    bool CsvReader::Read()
    {
    	while (_fileIsOpen && !_fi.eof())
    	{
    		_line.clear();
    		std::getline(_fi,_line);
    		if (_line.empty()) continue;
    		_lineData.clear();
    		CsvReader::SplitString(_line,_lineData,',');
    		if (_lineData.size() < _columnIndex.size())
    		{
    			continue;
    		}
    		return true;
    	}
    	return false;
    }
    
    void CsvReader::SplitString( const string & str, vector<string> & str_vec, char delimiter )
    {
    	if (str.empty())
    		return;
    	std::string::size_type pos = 0;
    	std::string::size_type pre_pos = 0;
    	while((pos = str.find_first_of(delimiter,pos)) != std::string::npos)
    	{
    		string tmp_str = str.substr(pre_pos,pos - pre_pos);
    		str_vec.push_back(tmp_str);
    		pre_pos = ++pos;
    	}
    	string tmp_str;
    	if (pre_pos < str.size())
    	{
    		tmp_str = string(&str[pre_pos]);
    	}
    	str_vec.push_back(tmp_str);
    }
    
    int CsvReader::GetColumnIndex( const string & columnName )
    {
    	ColumnIndexMap::const_iterator indexIt = _columnIndex.find(columnName);
    	if (indexIt != _columnIndex.end())
    	{
    		return indexIt->second;
    	}
    	return -1;
    }
    

      

  • 相关阅读:
    P1064 金明的预算方案
    P1164 小A点菜
    P1346 电车
    01背包二进制优化
    2018暑期多校1
    牛课第二次多校I
    STL
    Reachability from the Capital
    P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
    P3387 【模板】缩点
  • 原文地址:https://www.cnblogs.com/cmranger/p/4440430.html
Copyright © 2011-2022 走看看