Cocos2d-x Lua 读取Csv文件,更方便的使用数据

我的书上或者是我曾经出售的源码里,都有Csv文件的影子。

也许是先入为主吧,我工作那会用的最久的配置文件就是Csv,所以我在很多游戏里都会情不自禁地优先选择它。

Csv文件,格式很简单,就是一行一条数据,字段之间用逗号分隔,策划也可以方便地使用Excel进行编辑。

Csv格式的文件,解析起来也很简单,所以自己动手写写很快~(小若:我就喜欢拿来主义,你怎么着)

最近在用Lua写游戏,对于技能、怪物等配置,我还是选择用Csv~

不得不说,Lua等脚本语言,在某些方面是C++没法比的,这次我就用Csv来表达这种心情~

笨木头花心贡献,哈?花心?不,是用心~

转载请注明,原文地址:http://www.benmutou.com/archives/1634

文章来源:笨木头与游戏开发

一份Csv配置文件

我们来看看这样一份Csv文件,如图:

ID,Name,Des,Model
ID,名字,描述,图片模型
1,广告,www.benmutou.com,csv.png
2,否认,呵呵,广告什么的,我才不会加,good.png

(小若:这是图吗?是哪里是图啊!)

当然,这样好像不够清晰,我们来这样看看:

这是很简单的一个Csv文件:

第一行是英文名字,很重要,因为在代码里我们要通过这个名字来获取对应的字段内容。

第二行是中文名字,没什么作用,主要是给那些小白看的,比如旁白什么的。(小若:你的比如能不能不要这么有针对性?)

第三和第四行才是真正的内容,通常我都会给第一个字段设定为ID,这样可以根据ID轻松获取到对应行的内容。

Cocos Code IDE

OK,在读取Csv文件之前,稍微提一下这个IDE,它是Cocos2d-x官方出的一个IDE,专门针对Cocos2d-x+Lua、Cocos2d-x+JS,但不支持Cocos2d-x+C++。

虽然目前这个IDE还是RC版本,我是比较喜欢尝鲜的人,Cocos2d-x3.0版本我也是从Alpha玩起的~

就那句什么,“有坑才有成长”,我是这么认为的~

本文也是基于Cocos Code IDE来讲解,所以稍微提一下,IDE可以到官网下载,随便看看入门指引,几分钟的事情。

然后创建一个项目。

字符串分割

好了,项目创建完之后,默认有个main.lua和GameScene.lua,我们只需要在main.lua里做做测试就可以了

Csv是用逗号分割的,所以,字符串分割功能,必不可少,Lua似乎没有提供这个功能,幸好,这很简单。

在mian.lua里main函数前面添加一个函数:

function split(str, reps)
    local resultStrsList = {};
    string.gsub(str, ‘[^‘ .. reps ..‘]+‘, function(w) table.insert(resultStrsList, w) end );
    return resultStrsList;
end

split有两个参数,str当然就是准备被分割的字符串了,reps又当然是分隔符了~

这里用到了string库的gsub函数,共三个参数:

1. str ,待分割的字符串

2.’[^‘ .. reps ..‘]+’,这一看就是那什么,正则表达式,这货我很少用,所以每次用的时候就翻文档,用完就忘。

这里还比较简单,比如reps是逗号,那么,就变成 ‘[^,]+’  ,这个表达式的意思是:查找非逗号字符,并且多次匹配~

比如“heab,”,前面的heab都不是逗号,所有都匹配了,直到发现了第五个字符,它是逗号,停止匹配,于是最终匹配的字符串是“heab”。

3.每次分割完的字符串都能通过回调函数获取到,w参数就是分割后的一个子字符串,把它保存到一个table

OK,就这么简单,这样就能得到一个table,table里保存了所有被分割的子字符串。

测试一下,把默认的main函数的代码都删了,改成下面这个样子:

local function main()
    local t = split("nihfao,hehe,hen", ",");

    for k, v in pairs(t) do
        print(v);
    end
end

然后按F11运行,输出以下日志:

[LUA-print] nihfao

[LUA-print] hehe

[LUA-print] hen

成功了~

真正的解析Csv

我们的重点来了,解析Csv文件。 我们不仅仅是要解析,解析完,还要保存起来,方便以后取配置数据~

所以,为了以后更方便地读取数据,我想了一个好办法。

来看看代码,在mian函数的上面再加一个新函数:

function loadCsvFile(filePath)
    -- 读取文件
    local data = cc.FileUtils:getInstance():getStringFromFile(filePath);

    -- 按行划分
    local lineStr = split(data, ‘\n‘);

    --[[
                从第3行开始保存(第一行是标题,第二行是注释,后面的行才是内容) 

                用二维数组保存:arr[ID][属性标题字符串]
    ]]
    local titles = split(lineStr[1], ",");
    local ID = 1;
    local arrs = {};
    for i = 3, #lineStr, 1 do
        -- 一行中,每一列的内容
        local content = split(lineStr[i], ",");

        -- 以标题作为索引,保存每一列的内容,取值的时候这样取:arrs[1].Title
        arrs[ID] = {};
        for j = 1, #titles, 1 do
            arrs[ID][titles[j]] = content[j];
        end

        ID = ID + 1;
    end

    return arrs;
end

是不是很简单?(小若:简单个毛线啊!)

这可比在C++里解析要简单多了~

一句句来分析吧:

1.通过FileUtils的getStringFromFile函数读取文件,取得字符串内容

2.local lineStr = split(data, ‘\n’); 通过split函数,把文件内容按行分割,得到一个lineStr,它存放了每一行的内容

3.local titles = split(lineStr[1], “,”); 还记得我们的Csv文件吗?第一行内容是英文字母,它们很重要

这里把文件的第一行内容用逗号分割,得到titles,它存放了第一行的每一个字段。

这些字段有什么用呢?以后我们将通过这些字段来获取配置数据。

4.接着,新建一个table变量:local arrs = {}; 它将完整地保存解析后的Csv文件数据。

5.接下来有两个for循环。

先来看第一层循环:

for i = 3, #lineStr, 1 do
     — 一行中,每一列的内容
     local content = split(lineStr[i], “,”);

end

很早之前我们说过了,Csv的第一行是英文字段、第二行是中文解释,第三行才开始是真正的内容~所以我们要从第三行开始。

我们知道,Lua的table下标是从1开始的,于是,i的初始值为3

lineStr里存放的是每一行的内容,所以,第一层的for循环是为了取出每一行的内容,然后按逗号分割,保存到content变量里。

接下来,看第二层循环:

– 以标题作为索引,保存每一列的内容,取值的时候这样取:arrs[1].Title

arrs[ID] = {};
for j = 1, #titles, 1 do
      arrs[ID][titles[j]] = content[j];
end

arrs[ID] = {}是什么意思呢?这代表是一行的内容,arrs[ID]可以看做是一个数组,它保存了某一行的数据。

那么,arrs[ID]数组的下标自然就是我们的英文字母了(也就是之前一直说的,很重要的第一行内容)。

逻辑有点乱,我们慢慢理解:

虽然content保存了每一行的内容,但是它不方面获取数据,因为它的下标是数字。

所以,我们要把content的内容一个个复制到arrs[ID]里,把数字下标全部换成英文字符串。

第二层for循环就是在做这么一件事情。

测试一下

好了,就这么解释肯定还有点混乱吧,来测试一下就知道我倒底在说什么了。

修改main函数内容为:

local function main()
    local csvConfig = loadCsvFile("res/Mutou.Csv");

    print(csvConfig[1].Name .. ":" .. csvConfig[1].Des);
    print(csvConfig[2].Name .. ":" .. csvConfig[2].Des);
end

按F11运行,将输出以下日志:

[LUA-print] 广告:www.benmutou.com
[LUA-print] 否认:呵呵,广告什么的,我才不会加

首先,loadCsvFile会解析Csv文件,然后返回解析后的内容。

接着,我想获取ID为1的配置数据,比如,要获取它的Name字段属性,就非常简单了:csvConfig[1].Name 就可以了~

如果你对Lua的table比较生疏的话,你可能会无法理解本文的“精髓”(小若:因为根本就没有精髓啊!)

关于Lua的table,大家可以看看我的这篇文章,相信你会对table有一个初步的了解(足以看懂这篇文章)

巧说table的几种构造方式:http://www.benmutou.com/archives/627

后话

我个人是认为这么做很方便,我不是说这么解析很方便,而是,解析之后,要获取字段值的时候,很方便~

以后要给配置文件新增字段的话,对于解析和使用都完全没有影响,这是最舒服的地方。

当然了,这就要求我们的配置文件的第一行一定不能写错了,否则就不太好玩了。

如果是在C++里,可能就没法达到这么方便的程度了,虽然也能模仿,通过getValue(“key”)这样的方式也行~

但不管怎么说,还是不如脚本来得自然~

虽然它方便,但对于全脚本开发手游,还是不太舒服,有些地方,脚本完全比不上C++(不是指运行效率)~

好了,就说这么多~不拉仇恨了~

Cocos2d-x Lua 读取Csv文件,更方便的使用数据

时间: 2024-12-27 12:38:14

Cocos2d-x Lua 读取Csv文件,更方便的使用数据的相关文章

Lua读取CSV文件到table中

创建Lua函数载入CSV文件并保存到表中的函数: function GetLines(fileName) indx = 0 myLines ={} for line in io.line(string.format("%s%s", "c:/lua_scripts/",filename)) do indx = indx + 1 myLines[indx] = line end return indx, myLines --returns number of lines

PHP读取csv文件的内容

一次性读取csv文件内所有行的数据 <?php  $file = fopen('windows_2011_s.csv','r');  while ($data = fgetcsv($file)) { //每次读取CSV里面的一行内容 //print_r($data); //此为一个数组,要获得每一个数据,访问数组下标即可 $goods_list[] = $data;  } //print_r($goods_list); /* foreach ($goods_list as $arr){     

Spring Batch使用示例: 读取CSV文件并写入MySQL数据库

GitHub版本: https://github.com/kimmking/SpringBatchReferenceCN/blob/master/01_introduction/Spring_Batch_MySQL.md ------------ 编写批处理程序来处理GB级别数据量无疑是种海啸般难以面对的任务,但我们可以用Spring Batch将其拆解为小块小块的(chunk). Spring Batch 是Spring框架的一个模块,专门设计来对各种类型的文件进行批量处理. 本文先讲解一个简

sparkR读取csv文件

sparkR读取csv文件 The general method for creating SparkDataFrames from data sources is read.df. This method takes in the path for the file to load and the type of data source, and the currently active SparkSession will be used automatically. SparkR suppo

php读取csv文件类

php处理csv文件类: http://www.php100.com/cover/php/540.html <?php define("CSV_Start", 0); define("CSV_Quoted", 1); define("CSV_Quoted2", 2); define("CSV_Unquoted", 3); function readCSV($fh, $len, $delimiter = ',', $enc

读取csv文件,写入oracle数据库

/* * @(#)DataParse.java 2014年4月28日 */ package com.yihaodian.sa.doData; import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.sql.Connection;import java.

用程序读取CSV文件的方法

CSV全称 Comma Separated values,是一种用来存储数据的纯文本文件格式,通常用于电子表格或数据库软件.用Excel或者Numbers都可以导出CSV格式的数据. CSV文件的规则 0 开头是不留空,以行为单位.1 可含或不含列名,含列名则居文件第一行. 2 一行数据不垮行,无空行. 3 以半角符号,作分隔符,列为空也要表达其存在. 4 列内容如存在,,则用""包含起来. 5 列内容如存在""则用""""包

java读取csv文件

最近用到读取csv文件,以下是源码,读取csv文件,转化为一个String类型的list对象,其中对中午进行了处理,否则会出现乱码,filepath为csv文件的路径 /** * 读取csv文件 */ public static List<String> readCsv(String filepath){ List<String> list = new ArrayList<String>(); String inString = ""; try{ C

jmeter请求参数中文乱码及无法读取CSV文件解决办法

解决办法:参考http://blog.csdn.net/u012167045/article/details/70868306 版本:2.6 我是修改请求http请中的编码为Content encoding :utf-8 就正常了. 无法读取CSV文件: 可能是windows下路径有问题,在CSV Data Set Config 中filename修改为:E:\\edulogin.csv