cocos2d-x学习笔记——Csv文件读取工具

一个游戏中,通常会有很多怪物,以及怪物的生命值,魔法值等属性数据,这些数据不可能在代码里面写死,一般都会用配置文件来保存,使用时再加载到内存。
我们常用的配置文件是CSV文件,即逗号分隔值(Comma-Separated Values),如下图所示。

今天,我就来介绍一个来读取CSV文件的工具类——MyCsvUtil

在接受读取CSV文件工具类之前,先介绍一个读取字符串的工具类——StringUtil

//头文件StringUtil.h

#ifndef __StringUtil_H_
#define __StringUtil_H_
#include "cocos2d.h"

class StringUtil : public cocos2d::Ref
{
public:
    static StringUtil * getInstance();
    virtual bool init();

    //用分隔符分割字符窜,结果存放到一个列表中,列表中的对象为Value
    cocos2d::ValueVector split(const char * srcStr,const char * sSep);
private:
    static StringUtil * m_StringUtil;//Util 是工具的意思!
};


//函数实现文件
#include "StringUtil.h"
USING_NS_CC;

//初始化
StringUtil * StringUtil::m_StringUtil = nullptr;

StringUtil * StringUtil::getInstance()
{
    if (m_StringUtil == nullptr)
    {
        m_StringUtil = new StringUtil();
        if (m_StringUtil && m_StringUtil->init() )
        {
            m_StringUtil->autorelease();
            m_StringUtil->retain();
        }
        else
        {
            CC_SAFE_DELETE(m_StringUtil);
            m_StringUtil = nullptr;
        }
    }
    return m_StringUtil;
}

bool StringUtil::init()
{

    ////拆分字符串
    //auto strsList = StringUtil::getInstance()->split("zhaolong,want,to,work!",",");
    //for (auto str : strsList)
    //{
    // log("str = %s",str.asString().c_str());
    //}

    return true;
}

//分离函数,srcStr是要进行分离的字符串,sSep是分隔符 separator
ValueVector StringUtil::split(const char * srcStr,const char * sSep)
{
    ValueVector stringList; //typedef std::vector<Value> ValueVector;
    int size = strlen(srcStr);
    //将数据转换为字符串对象
    Value str = Value(srcStr);
    int startIndex = 0;
    int endIndex = 0;
    endIndex = str.asString().find(sSep);

    std::string lineStr;
    //根据分隔符拆分字符串,并添加到列表中
    while (endIndex > 0)
    {
        //拆分的字符串
        //substr函数的作用是从给定的字符表达式或备注字段中返回一个子字符串。
        lineStr = str.asString().substr(startIndex,endIndex);
        //放入列表中
        stringList.push_back(Value(lineStr));

        //更新要分离的字符串
        str = Value(str.asString().substr(endIndex + 1,size));
        //更新索引号
        endIndex = str.asString().find(sSep);
    }
    //剩下的字符串也添加进入列表
    //将剩下的字符串与空字符串相比,若不为空
    if (str.asString().compare("") != 0)
    {
        //就把该字符串放入到列表中
        stringList.push_back(Value(str.asString()));
    }
    return stringList;
}
#endif

上面那个字符串工具类,最主要的就是一个split函数,因为已经写了足够多的注释了,这里就不再多做解释了。以后要进行字符串读取的话只需要将这个头文件包含进去,再调用split函数就行了。

下面开始讲解真正的Csv文件读取类

我们要想更好的处理和保存csv文件数据,我们应该把它当作对象来处理,新建一个CsvData类,他的类对象就代表一份Csv文件数据。

//头文件CsvData.h
#ifndef __CsvData_H_
#define __CsvData_H_
#include "cocos2d.h"

class CsvData : public  cocos2d::Ref
{
public:
    CREATE_FUNC(CsvData);
    virtual bool init();

    //添加一行数据
    void addLineData(cocos2d::ValueVector lineData);
    //获取某行的数据
    cocos2d::ValueVector getSingleLineData(int iLine);
    //获取行列大小
    cocos2d::Size getRowColNum();

private:
    //用来存放Csv文件所有行的数据
    cocos2d::ValueVector m_allLinesVec;
};


//函数实现文件
#include "CsvData.h"
USING_NS_CC;
bool CsvData::init()
{
    return true;
}

void CsvData::addLineData(ValueVector lineData)
{
    m_allLinesVec.push_back(Value(lineData));
}

ValueVector CsvData::getSingleLineData(int iLine)
{
    return m_allLinesVec.at(iLine).asValueVector();
}

Size CsvData::getRowColNum()
{
    Size size = Size();
    //获得Csv文件的行数,因为m_allLinesVec变量保存的就是每一行的数据,所以m_allLinesVec的大小就是行的数量
    size.width = m_allLinesVec.size();
    //如果Csv文件中的行数大于0
    if (size.width > 0)
    {
        //就求Csv文件第0行的数据的个数,得到列的数量
        size.height = m_allLinesVec.at(0).asValueVector().size();
    }

    return size;
}
#endif

这个CsvData类比较简单,不必多说了,只需要注意的是getRowColNum这个函数。这个函数是获取Csv文件的规模,即行数和列数(行号和列号都是从0开始的)。
因为Csv文件保存的就是每一行的数据,所以Csv的size大小就是行的数量,要求列数的话,就求Csv文件第0行的数据的个数,得到列的数量。

然后,然后就是真正的编写Csv文件读取工具类啦!

//头文件MyCsvUtil.h
#ifndef __MyCsvUtil_H_
#define __MyCsvUtil_H_
#include "CsvData.h"

class MyCsvUtil : public cocos2d::Ref
{
public:
    static MyCsvUtil * getInstance();
    virtual bool init();

    //加载配置文件
    void loadFile(const char * sPath);
    //获取某行某列的值
    cocos2d::Value getValue(int iRow,int iCol,const char * csvFilePath);
    //获取值并转化为字符串
    const std::string getStr(int iRow,const char * csvFilePath);
    //获取值并转换为整形
    const int getInt(int iRow,const char * csvFilePath);
    //获取文件的行和列的数量
    const cocos2d::Size getFileSize(const char * csvFilePath);

private:
    static MyCsvUtil * ms_CsvUtil;
    cocos2d::Map<std::string,CsvData *> m_CsvMap;
};

#endif


//函数实现文件
#include "MyCsvUtil.h"
#include "StringUtil.h"
USING_NS_CC;

MyCsvUtil * MyCsvUtil::ms_CsvUtil = nullptr;

MyCsvUtil * MyCsvUtil::getInstance()
{
    if (ms_CsvUtil == nullptr)
    {
        ms_CsvUtil = new MyCsvUtil();
        if (ms_CsvUtil && ms_CsvUtil->init() )
        {
            ms_CsvUtil->autorelease();
            ms_CsvUtil->retain();
        }
        else
        {
            CC_SAFE_DELETE(ms_CsvUtil);
            ms_CsvUtil = nullptr;
        }
    }
    return ms_CsvUtil;
}

bool MyCsvUtil::init()
{
    if (!TBack::init())
    {
        return false;
    }
    return true;
}

//加载文件
void MyCsvUtil::loadFile(const char * sPath)
{
    //存放一个csv文件的对象
    CsvData * csvData = CsvData::create();
    //读取路径所在文件的数据,保存到列表中
    std::string str = FileUtils::getInstance()->getStringFromFile(sPath);
    //将得到的数据按换行符分开,放到列表中
    ValueVector linesList = StringUtil::getInstance()->split(str.c_str(),"\n");
    //把每一行的字符拆分开来(按都好分隔)
    for (auto value : linesList)
    {
        //将一行的字符串按逗号分隔,然后存放到列表中,最后将列表存放到CsvData对象里
        //换句话说,csvData将成为一个二维表格,记录了配置文件行和列的字符串
        ValueVector tArr = StringUtil::getInstance()->split(value.asString().c_str(),",");
        csvData->addLineData(tArr);
    }
    //将CsvData对象添加到字典里
    m_CsvMap.insert(sPath,csvData);
}

//获取文件规格
const Size MyCsvUtil::getFileSize(const char * csvFilePath)
{
    //取出配置文件的二维表格
    auto csvData = m_CsvMap.at(csvFilePath);
    //如果配置文件不存在,则加载配置文件
    if (csvData == nullptr)
    {
        loadFile(csvFilePath);
        csvData = m_CsvMap.at(csvFilePath);
    }
    //调用了csvData类的函数
    Size size = csvData->getRowColNum();
    return size;
}

//获取文件某行某列
Value MyCsvUtil::getValue(int iRow,const char * csvFilePath)
{
    auto csvData = m_CsvMap.at(csvFilePath);
    if (csvData == nullptr)
    {
        loadFile(csvFilePath);
        csvData = m_CsvMap.at(csvFilePath);
    }
    //获取第iRow行数据
    ValueVector rowVector = csvData->getSingleLineData(iRow);
    //获取第iCol列数据
    Value colValue = rowVector.at(iCol);

    return colValue;
}

//获取文件某行某列并转换为字符串
const std::string MyCsvUtil::getStr(int iRow,const char * csvFilePath)
{
    Value val = Value();
    val = getValue(iCol,iCol,csvFilePath);
    return val.asString();
}

//获取文件某行某列并转换为整型
const int MyCsvUtil::getInt(int iRow,const char * csvFilePath)
{
    Value val = Value();
    val = getValue(iRow,csvFilePath);
    return val.asInt();
}

最后,我们就可以在其他的程序里面包含这个Csv文件读取工具类的头文件,就可以使用它了。
这是我在调试模式下测试的结果:

#include "MyCsvUtil.h"

/*------测试代码段-------*/

const char * sPath = "monster.csv";//文件路径
MyCsvUtil::getInstance()->loadFile(sPath);//加载文件
//获得第1行第1列数据
Value firstMonsterName = MyCsvUtil::getInstance()->getValue(1,1,sPath);
//获得第2行第1列数据
Value secMonsterName = MyCsvUtil::getInstance()->getValue(2,sPath);   
//打印结果
log("%s",firstMonsterName.asString().c_str());
log("%s",secMonsterName.asString().c_str());

输出结果:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是