cocos2dx游戏开发学习——CSV文件解析

在cocos2dx项目中,我们经常会用到CSV文件。这里直接上代码。
ALCsvUtil.h

/**
 *  CSV 解析工具
 */
#ifndef ALCsvUtil_h
#define ALCsvUtil_h

#include <vector>
#include <map>
#include <string>

typedef std::vector<std::string> StrVec;

typedef std::vector< StrVec > StrDict;

typedef std::map< std::string, StrDict> CsvMap;



class ALCsvUtil
{
public:
    static ALCsvUtil* getInstance();

    static void destroyInstance();

    /**
     *  add csv file to dict
     *
     *  @param sPath is csv file path
     */
    virtual bool addFileData(const std::string &rSCsvFilePath);

    /**
     *  del csv file to dict
     *
     *  @param sPath is csv file path
     */
    virtual void releaseFile(const std::string &rSCsvFilePath);

    /**
     *  get some row and some column value from some csv file
     *
     *  @param rRow        is row num
     *  @param rCol        is column num
     *  @param csvFilePath is some csv file
     *
     *  @return some row and some column real TextValue IntValue, DoubleValue,if this pos not be exsit return ""
     */
    virtual std::string getText(const int &rRow, const int &rCol, const std::string &rSCsvFilePath);
    virtual int getInt(const int &rRow, const int &rCol, const std::string &rSCsvFilePath);
    virtual double getDouble(const int &rRow, const int &rCol, const std::string &rSCsvFilePath);

    /**
     *  get some file row data
     *
     *  @param iRow          is row num
     *  @param rSCsvFilePath is some csv file
     *
     *  @return some row data
     */
    virtual StrVec getRowData(const int &rIRow, const std::string &rSCsvFilePath);

    /**
     *  get csv file row and column save tuple<int, int>
     *
     *  @param rSCsvFilePath csv file path
     *
     *  @return csv file row, column in tuple<int, int>
     */
    virtual std::tuple<int, int> getFileRowColNum(const std::string &rSCsvFilePath);

    /**
     *  find dest value in csv file row num
     *
     *  @param rSValue       find value
     *  @param rIValueCol    value column
     *  @param rSCsvFilePath csv file path
     *
     *  @return value in csv row
     */
    virtual int findValueInWithLine(const std::string &rSValue, const int &rIValueCol, const std::string &rSCsvFilePath);


protected:
    /**
     *  get csv file string vec
     *
     *  @param rSCsvFilePath csv file path
     *
     *  @return csv file strVec
     */
    virtual StrDict &getFileDict(const std::string &rSCsvFilePath);

    virtual ~ALCsvUtil();

    /**
     *  get csv file string vec
     *
     *  @param rSCsvFilePath csv file path
     *
     *  @return csv file strVec
     */
    /**
     get string vec by split

     @param rSSrcStr content
     @param rSSep  Seperator
     @return std::vector<std::string>
     */
    StrVec split(const std::string &rSSrcStr, const char &rSSep);


private:
    ALCsvUtil();

    ALCsvUtil(const ALCsvUtil &rCsvUtil) = delete;

    ALCsvUtil &operator=(const ALCsvUtil &rCsvUtil) = delete;


private:
    static ALCsvUtil* _gInstance;

    CsvMap* _pCsvMap;
};

#endif /* ALCsvUtil_h */

ALCsvUtil.cpp

//
//  ALCsvUtil.cpp
//  GameTest-mobile
//
//  Created by Allen on 2018/7/2.
//

#include "ALCsvUtil.h"


ALCsvUtil* ALCsvUtil::_gInstance;

ALCsvUtil::ALCsvUtil():_pCsvMap(nullptr)
{
    _pCsvMap = new CsvMap();
}

ALCsvUtil::~ALCsvUtil()
{
    CC_SAFE_DELETE(_pCsvMap);
}

ALCsvUtil* ALCsvUtil::getInstance()
{
    if (!_gInstance) {
        _gInstance = new ALCsvUtil();
    }
    return _gInstance;
}

void ALCsvUtil::destroyInstance()
{
    if (_gInstance) {
        CC_SAFE_DELETE(_gInstance);
    }
}

bool ALCsvUtil::addFileData(const std::string &rSCsvFilePath)
{
    if (std::string("") == rSCsvFilePath) return false;


    if (!cocos2d::FileUtils::getInstance()->isFileExist(rSCsvFilePath)) {
        CCLOG("ALCsvUtil::addFileData():  %s file could not be found",rSCsvFilePath.c_str());
        return false;
    }
    cocos2d::Data csvData = cocos2d::FileUtils::getInstance()->getDataFromFile(rSCsvFilePath);
    if (!csvData.getBytes()) {
        CCLOG("ALCsvUtil::addFileData():  %s file is null",rSCsvFilePath.c_str());
        return false;
    }
    StrVec linesVec = split((char*)csvData.getBytes(), '\n');
    StrVec strsVec;
    StrDict dict;
    for (const auto &linesVecIter :linesVec) {
        std::string lineStr(linesVecIter);
        if (lineStr[lineStr.length() - 1] == '\r') {
            lineStr = lineStr.substr(0,lineStr.length() - 1);
        }
        strsVec = split(lineStr, ',');
        dict.push_back(strsVec);
    }
    _pCsvMap->insert(std::make_pair(std::string(rSCsvFilePath), dict));
    return true;
}

void ALCsvUtil::releaseFile(const std::string &rSCsvFilePath)
{
    _pCsvMap->erase(rSCsvFilePath);
}

std::tuple<int,int> ALCsvUtil::getFileRowColNum(const std::string &rSCsvFilePath)
{
    auto dict = getFileDict(rSCsvFilePath);
    int rowNum = (int) dict.size();
    int colNum = (int) (*(dict.begin())).size();
    return std::make_tuple(colNum,rowNum-1);
}

std::string ALCsvUtil::getText(const int &rRow, const int &rCol, const std::string &rSCsvFilePath)
{
    const auto dict = getFileDict(rSCsvFilePath);
    CCASSERT(rRow < dict.size() && rCol < dict.at(rRow).size(), "ALCsvUtil: (row or col) out of range in getObjectAtIndex() ");
    return dict.at(rRow).at(rCol);
}

int ALCsvUtil::getInt(const int &rRow, const int &rCol, const std::string &rSCsvFilePath)
{
    return atoi(getText(rRow, rCol, rSCsvFilePath).c_str());
}

double ALCsvUtil::getDouble(const int &rRow, const int &rCol, const std::string &rSCsvFilePath)
{
    return atof(getText(rRow, rCol, rSCsvFilePath).c_str());
}

StrVec ALCsvUtil::getRowData(const int &rIRow, const std::string &rSCsvFilePath)
{
    auto tRow = std::get<1>(getFileRowColNum(rSCsvFilePath));

    if(rIRow > tRow) return StrVec();

    return  _pCsvMap->at(rSCsvFilePath).at(rIRow);
}

StrDict &ALCsvUtil::getFileDict(const std::string &rSCsvFilePath)
{
    CCASSERT((_pCsvMap->end() != _pCsvMap->find(rSCsvFilePath) || addFileData(rSCsvFilePath)),"ALCsvUtil: load csvFile file");
    return _pCsvMap->at(rSCsvFilePath);
}

int ALCsvUtil::findValueInWithLine(const std::string &rSValue, const int &rIValueCol, const std::string &rSCsvFilePath)
{
    auto iRowCount = std::get<1>(getFileRowColNum(rSCsvFilePath));

    auto ret = -1;
    std::string findValue(rSValue);

    for (int iRow = 0; iRow < iRowCount; ++iRow)
    {
        std::string tmpValue = getText(iRow, rIValueCol, rSCsvFilePath);
        if (findValue == tmpValue)
        {
            ret = iRow;
            break;
        }
    }
    return ret;
}

StrVec ALCsvUtil::split(const std::string &rSSrcStr, const char &rSSep)
{
    StrVec strList;

    std::string::size_type lastIndex = rSSrcStr.find_first_not_of(rSSep,0);
    std::string::size_type currentIndex = rSSrcStr.find_first_of(rSSep,lastIndex);
    while (std::string::npos != currentIndex || std::string::npos != lastIndex)
    {
        strList.push_back(rSSrcStr.substr(lastIndex,currentIndex - lastIndex));
        lastIndex = rSSrcStr.find_first_not_of(rSSep,currentIndex);
        currentIndex = rSSrcStr.find_first_of(rSSep,lastIndex);
    }

    return strList;
}

猜你喜欢

转载自blog.csdn.net/allen_ww/article/details/80894905