CSV解析

头文件


#include <fstream>
#include <vector>
#include <string>

#if 0
#define uxNULL 0
#define uxOK  0
#define uxERROR 1
#define u8 unsigned char
#define s32 int
#define u32 unsigned int
#define f32 float
#endif

class CsvFile
{
    public:
    CsvFile();
    virtual ~CsvFile();

    // 文件加载
    u32 loadFromFile(const std::string& fileName, bool hasHead = true);
    u32 saveToFile(u8* szFilePath = nullptr);

    // 读取表头
    template<class T>
    u32 getHeaderValue(s32 col, T& val, s32 row = 0);

    // 读取单元格
    template<class T>
    u32 getCellValue(s32 row, s32 col, T& val);

    // 表格内容
    s32 getRowCount();

    // 获取指定行的列数
    s32 getColCount(s32 row);

    // 获取最大最小列数
    s32 getColMaxMin(s32& maxCols, s32& minCols);

	// 获取表头, 默认为一行
	std::vector<std::string>* getHeader(s32 row = 0);

    // 获取一行
    std::vector<std::string>* getRow(s32 row);

protected:

    // 数据转换
	template<class out_type, class in_value>
    out_type convert(const in_value& t);

    // 清空结果
    u32 clear();

    // 解析文件
    bool parse();

    // 打开关闭文件
    bool openFile(std::ifstream & hFile);
    void closeFile(std::ifstream& hFile);
	bool openFile(std::ofstream& hFile);
	void closeFile(std::ofstream& hFile);

    // 解析单行
    void parseLine(std::string line, std::vector<std::string>& values);

    // 存放数据
    std::vector<std::vector<std::string>> m_vecHeader;

    // 存放数据
    std::vector<std::vector<std::string>> m_vecContent;

    // 配置
    std::string m_szFileName;
    bool m_bHasHeader;
    

};

cpp文件


CsvFile::CsvFile()
{

}
CsvFile::~CsvFile()
{

}

// 文件加载
u32 CsvFile::loadFromFile(const std::string& fileName, bool hasHead)
{
    m_szFileName = fileName;
    m_bHasHeader = hasHead;

    // 解析
    this->parse();

    return uxOK;
}

// 保存文件
u32 CsvFile::saveToFile(u8* szFilePath)
{
    // 暂不实现
    return uxOK;
}

template<class out_type, class in_value>
out_type CsvFile::convert(const in_value& t)
{
	std::stringstream stream;
	stream << t;
	out_type result;
	stream >> result;
	return result;
}

// 读取表头
template<class T>
u32 CsvFile::getHeaderValue(s32 col, T& val, s32 row)
{
    std::vector<std::string>* pRow = getHeader(row);
    if (pRow)
    {
        if (col < pRow->size())
        {
            std::string str = pRow->at(col);
            val = convert<T>(str);
        }
    }
    return uxERROR;
}

// 读取单元格
template<class T>
u32 CsvFile::getCellValue(s32 row, s32 col, T& val)
{
	std::vector<std::string>* pRow = getRow(row);
	if (pRow)
	{
		if (col < pRow->size())
		{
			std::string str = pRow->at(col);
			val = convert<T>(str);
		}
	}
	return uxERROR;
}


// 表格内容
s32 CsvFile::getRowCount()
{
    return m_vecContent.size();
}

// 获取行数
s32 CsvFile::getColCount(s32 row)
{
    if (row < m_vecContent.size())
    {
        return m_vecContent.at(row).size();
    }
    return 0;
}

// 获取最大最小列数
s32 CsvFile::getColMaxMin(s32& iMaxCols, s32& iMinCols)
{
    iMinCols = 0x7FFFFFFF;
    iMaxCols = 0;

    for (s32 row = 0; row < m_vecContent.size(); row++)
    {
        s32 iThisCols = m_vecContent.at(row).size();
        if (iThisCols > iMaxCols)
        {
            iMaxCols = iThisCols;
        }
        if (iThisCols < iMinCols)
        {
            iMinCols = iThisCols;
        }
    }

    return uxOK;
}


// 获取表头, 默认为一行
std::vector<std::string>* CsvFile::getHeader(s32 row)
{
	if (row < m_vecHeader.size())
	{
		return &m_vecHeader.at(row);
	}
	return uxNULL;
}

// 获取一行
std::vector<std::string>* CsvFile::getRow(s32 row)
{
    if (row < m_vecContent.size())
    {
        return &m_vecContent.at(row);
    }
    return uxNULL;
}

// 清空数据内容
    u32 CsvFile::clear()
    {
        m_vecContent.clear();
        m_vecHeader.clear();
        return uxOK;
    }

    // 解析
    bool CsvFile::parse()
    {
        std::ifstream hFile;

        // 打开文件
        if (!this->openFile(hFile))
        {
            return false;
        }
        bool m_fist = true;
        std::string line;
        while (!hFile.eof())
        {
            line.clear();
            std::getline(hFile, line);
            if (line.size() > 0)
            {
                std::vector<std::string> vals;

                // 解析单行
                this->parseLine(line, vals);

                if (m_fist && m_bHasHeader)
                {
                    // 记录为表头
                    m_vecHeader.push_back(vals);

                    m_fist = false;
                    continue;
                }

                // 记录为内容
                m_vecContent.push_back(vals);
            }
        }

        // 关闭文件
        this->closeFile(hFile);

        return uxOK;
    }

    // 解析一行
    void CsvFile::parseLine(std::string szLine, std::vector<std::string>& vecValues)
    {
        vecValues.clear();
        //末尾补逗号方便统一处理
        if (szLine[szLine.size() - 1] != ',')
        {
            szLine += ',';
        }

        const int len = szLine.size();
        std::string colStr;
        int marksCount = 0;//引号个数
        for (int i = 0; i < len; i++)
        {
            if (szLine[i] == '"')
            {
                ++marksCount;
            }
            //遇到逗号并且引号个数为偶数个,一个列名称结束
            else if ((szLine[i] == ',') && (marksCount % 2 == 0))
            {
                std::string colVal;
                for (int k = 0; k < colStr.size(); k++)
                {
                    //去掉头尾的引号
                    if ((k == 0 || k == colStr.size() - 1) && colStr[k] == '"')
                    {
                        continue;
                    }

                    colVal += colStr[k];
                    if (colStr[k] == '"' && colStr[k + 1] == '"')
                    {
                        ++k;
                    }
                }
                vecValues.push_back(colVal);
                colStr.clear();
                marksCount = 0;
                continue;
            }

            colStr += szLine[i];
        }
    }


    // 打开文件
    bool CsvFile::openFile(std::ifstream& hFile)
    {
        if (hFile.is_open())
        {
            return true;
        }
        hFile.open(m_szFileName);
        if (!hFile.is_open())
        {
            printf("Open file fail.[%s].\n", m_szFileName.c_str());
            return false;
        }
        return true;
    }

	// 关闭文件
	void CsvFile::closeFile(std::ifstream& hFile)
	{
		if (hFile.is_open())
		{
			hFile.close();
		}
	}

	// 打开文件
	bool CsvFile::openFile(std::ofstream& hFile)
	{
		if (hFile.is_open())
		{
			return true;
		}
		hFile.open(m_szFileName);
		if (!hFile.is_open())
		{
			printf("Open file fail.[%s].\n", m_szFileName.c_str());
			return false;
		}
		return true;
	}


	// 关闭文件
	void CsvFile::closeFile(std::ofstream& hFile)
	{
		if (hFile.is_open())
		{
			hFile.close();
		}
	}

测试文件

"col1,","co""l2","""col3""","col,4"",""4",,col6
4,5,6,41,56,66
7,8,9,42,58,68
10,11,12,43,,
13,14,15,44,,
16,17,18,45,,
19,20,21,46,,
22,23,24,47,,
25,26,27,48,,
28,29,30,49,,
31,32,33,50,,

,

32,33,34,51,,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值