Cocos2dx杂记:cocos2dx解析csv格式文件

cocos2dx解析CSV 立即下载

游戏存储或者配置经常使用到逗号分隔文件,如何实现解析呢?

下面直接上代码

1、头文件CSVParser.h

#pragma once
#include "cocos2d.h"
#include <vector>
#include <string>
using namespace  std;

USING_NS_CC;

namespace CSVParser {

    // 每一行的记录
    class Row
    {
    public:
        Row() { }
        ~Row() { }

        void push_back(const string& value) { m_values.push_back(value); }
        void setHeader(const vector<string>* header) { m_header = header; }

    public:

        // 每行数据有多少字段
        unsigned int size() const { return m_values.size(); }

        // 运算符 [] 重载
        string& operator[](unsigned int key)
        {
            if (key < size()) return m_values[key];
            throw "can't return this value (doesn't exist)";
        }

        // 运算符 [] 重载
        string& operator[](const string& key)
        {
            vector<string>::const_iterator it;
            int pos = 0;
            for (it = (*m_header).begin(); it != (*m_header).end(); it++) {
                if (key == *it) return m_values[pos];
                pos++;
            }
            throw "can't return this value (doesn't exist)";
        }

    private:
        const vector<string>* m_header;
        vector<string> m_values;
    };


    class Csv
    { 
    public:
        Csv(const string& filename);
        ~Csv();

        // 解析csv文件
        void Parse(const string& filename);

        // 错误信息
        const string& getErrorInfo() const { return m_strErrorInfo; }

        // 获取列头字段
        vector<string> getHeader() const { return m_header; }
        // 获取总行数
        unsigned int getRowCount() const { return m_content.size(); }
        // 获取总列数
        unsigned int getColumnCount() const { return m_header.size(); }
        // 运算符 [] 重载
        Row& operator[](unsigned int key);

    private:
        // 读取整个文件的数据
        void Load(const string& filename, string& Data);
        void setHeader();

    private :
        // 原始表格数据
        vector<Row> m_content;   // 所有行的数据(包含列头)
        vector<string> m_header; // 列头字段
        // 错误信息
        string m_strErrorInfo;
    };
}

2、实现CSVParser.cpp

#include "CSVParser.h"

namespace CSVParser {

    Csv::Csv(const string& filename) {
        Parse(filename);
    }

    Csv::~Csv() {

    }

    void Csv::Load(const string& filename, string& Data)
    {
        ssize_t len = 0;
        unsigned char *data = NULL;
        auto strPath = FileUtils::getInstance()->fullPathForFilename(filename);

        data = FileUtils::getInstance()->getFileData(strPath.c_str(),"r", &len);

        Data.assign((char *)data, len);

        free(data);
    }


    void Csv::Parse(const string& filename)
    {
        // 清除之前的数据
        m_content.clear();
        m_strErrorInfo.clear();

        string text;
        Load(filename, text);

        if (text.size() == 0) {
            return;
        }

        // 定义状态
        enum StateType {
            NewFieldStart,      // 新字段开始
            NonQuotesField,     // 非引号字段
            QuotesField,        // 引号字段
            FieldSeparator,     // 字段分隔
            QuoteInQuotesField, // 引号字段中的引号
            RowSeparator,       // 行分隔符字符1,回车
            Error,              // 语法错误
        };

        Row Fields = Row();
        string strField;

        // 设置初始状态
        StateType State = NewFieldStart;

        for (int i = 0, size = text.size(); i < size; ++i) {
            const char& ch = text[i];

            switch (State) {
                case NewFieldStart: { // 新字段开始
                    if (ch == '"') {
                        State = QuotesField;
                    }
                    else if (ch == ',') {
                        Fields.push_back("");
                        State = FieldSeparator;
                    }
                    else if (ch == '\r' || ch == '\n') {
                        m_strErrorInfo = "语法错误:有空行";
                        State = Error;
                    }
                    else {
                        strField.push_back(ch);
                        State = NonQuotesField;
                    }
                }
                break;

                case NonQuotesField: { // 非引号字段
                    if (ch == ',') {
                        Fields.push_back(strField);
                        strField.clear();
                        State = FieldSeparator;
                    }
                    else if (ch == '\r') {
                        Fields.push_back(strField);
                        State = RowSeparator;
                    }
                    else {
                        strField.push_back(ch);
                    }
                }
                break;

                case QuotesField: { // 引号字段
                    if (ch == '"') {
                        State = QuoteInQuotesField;
                    }
                    else {
                        strField.push_back(ch);
                    }
                }
                break;

                case FieldSeparator: { // 字段分隔
                    if (ch == ',') {
                        Fields.push_back("");
                    }
                    else if (ch == '"') {
                        strField.clear();
                        State = QuotesField;
                    }
                    else if (ch == '\r') {
                        Fields.push_back("");
                        State = RowSeparator;
                    }
                    else {
                        strField.push_back(ch);
                        State = NonQuotesField;
                    }
                }
                break;

                case QuoteInQuotesField: { // 引号字段中的引号
                    if (ch == ',') {
                        // 引号字段闭合
                        Fields.push_back(strField);
                        strField.clear();
                        State = FieldSeparator;
                    }
                    else if (ch == '\r') {
                        // 引号字段闭合
                        Fields.push_back(strField);
                        State = RowSeparator;
                    }
                    else if (ch == '"') {
                        // 转义
                        strField.push_back(ch);
                        State = QuotesField;
                    }
                    else {
                        m_strErrorInfo = "语法错误: 转义字符 \" 不能完成转义 或 引号字段结尾引号没有紧贴字段分隔符";
                        State = Error;
                    }
                }
                break;

                case RowSeparator: { // 行分隔符字符1,回车
                    if (ch == '\n') {
                        m_content.push_back(Fields);
                        Fields = Row(); // Fields.clear();
                        strField.clear();
                        State = NewFieldStart;
                    }
                    else {
                        m_strErrorInfo = "语法错误: 行分隔用了回车 \\r。但未使用回车换行 \\r\\n ";
                        State = Error;
                    }
                }
                break;

                case Error: { // 语法错误
                    return;
                }
                break;

                default: break;
            }
        }
        // end for

        switch (State) {
            case NewFieldStart: {
                // Excel导出的CSV每行都以/r/n结尾。包括最后一行
            }
            break;

            case NonQuotesField: {
                Fields.push_back(strField);
                m_content.push_back(Fields);
            }
            break;

            case QuotesField: {
                m_strErrorInfo = "语法错误: 引号字段未闭合";
            }
            break;

            case FieldSeparator: {
                Fields.push_back("");
                m_content.push_back(Fields);
            }
            break;

            case QuoteInQuotesField: {
                Fields.push_back(strField);
                m_content.push_back(Fields);
            }
            break;

            case RowSeparator: {

            }
            break;

            case Error: {

            }
            break;

            default: break;
        }

        setHeader();
    }


    void Csv::setHeader()
    {
        m_header.clear();
        for (unsigned int i = 0; i < m_content[0].size(); i++) {
            m_header.push_back(m_content[0][i]);
        }
        for (unsigned int i = 0; i < m_content.size(); i++) {
            m_content[i].setHeader(&m_header);
        }
    }


    Row& Csv::operator[](unsigned int key)
    {
        if (key < m_content.size()) return m_content[key];
        throw "can't return this row (doesn't exist)";
    }
}

3、下载地址
CSVParser

CSVParser:解析 CSV 文件。-开源 一个简单的 CSV 解析器。 非常容易使用。 立即下载

相关推荐

Hi3516CV610 YOLOv8模型转换与部署实战:从源码到板端推理全流程解析

本文详细解析了Hi3516CV610开发板上YOLOv8模型的转换与部署全流程,包括模型转换、量化、编译和部署等关键步骤。通过实战案例和避坑指南,帮助开发者高效实现从PyTorch模型到嵌入式设备的推理优化,适用于智能门禁、视频分析等实时场景。

weixin_30790841的博客 650

(4)cocos2dx读取csv数据文件

cocos2dx中读取数据文件可能有很多种,像读取xml,lua,csv,json等,这些都可以作为配置数据的格式。 最近用到了读取csv数据文件,所以在网上找了一下关于这方面的技术博客。果然,网上各路大神都是不吝啬的, 不说废话了,直接上代码。代码如下(测试通过,可读取数据): .h头文件   // // QLCSVFile.h // // Created by quasi_le...

QuasiLee的记录 1088

荔枝派Lichee Nano全志F1C100s烧录避坑指南:从Fel模式到SPI Flash完整流程

本文详细介绍了荔枝派Lichee Nano基于全志F1C100s芯片的SPI Flash烧录完整流程,从FEL模式进入技巧到定制化sunxi-tools编译,再到分区策略与实战烧录步骤。针对开发者常见的烧录程序问题提供了专业解决方案,帮助用户高效完成嵌入式系统部署。

tea88的博客 787

在cocos2dx中解析CSV文件

本文主要是用C++简单的实现了cocos2dx中对CSV文件的解析,由于能力有限,写的不好的地方提出来共同学习共同进步, 这里参考了笨木头使用LUA解析CSV文件点击打开链接还参考了另一位仁兄的C++代码,网址找不到了,真是抱歉 首先需要补充一点概念:什么是CSV文件?? 就是一行为一条记录,每条记录以","作为分隔符啦划分字段(哈,详细内容请自行百度~~~) ID,NAME,SEX,YE

漂浮一生的专栏 1043

vTaskStartScheduler()详解

是启动 FreeRTOS 实时内核的“扳机”。在调用它之前,你只是创建了一些任务结构,但它们都处于“待命”状态,系统仍然在按传统的裸机前后台方式运行。调用这个函数后,FreeRTOS 内核会接管系统的控制权,开始根据优先级调度你创建的任务,多任务环境才真正开始。关键点:它没有参数。它的所有行为都由中的配置宏控制。它通常不会返回。一旦调用,除非没有任务可以运行(或者你显式地停止了调度器),否则程序流永远不会回到main()函数中调用它的下一行。是一个没有参数但行为由精密控制的函数。

Shylock_Mister的博客 1591

无源定位入门(二):FDOA(2)信号模型和原理

信号模型 假设地面固定目标信号源位置为 ,有M架飞机随机分布在空中,并作匀速直线运动。时刻t的时候第i架飞机的位置为,飞行速率为 , 假设目标的信号中心频率为 ,电磁波的传播速度为 ,则此时每个飞机接收目标信号的频率为 以第1架飞机为参考基站,目标信号到达第n架飞机和参考基站之间的FDOA 测量值可表示为 ...

syy_1797的博客 5955

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

在cocos2dx项目中,我们经常会用到CSV文件。这里直接上代码。 ALCsvUtil.h /** * CSV 解析工具 */ #ifndef ALCsvUtil_h #define ALCsvUtil_h #include <vector> #include <map> #include <string> ...

Allen_ww的博客 336

2023年LitCTF web组wp

1、导弹迷踪2、1zjs3、php是世界上最好的语言!!4、Ping5、我Flag呢?7、作业管理系统8、Vim yyds10、这是什么?SQL!注一下!11、Flag点击就送!12、就当无事发生13、彩蛋。

m0_74160536的博客 1587

cocos2dx 3.x 读取csv

#ifndef _PARSE_CSV_H_ #define _PARSE_CSV_H_ #include #include #include #include #include using namespace std; struct CsvData { string FileName; map > TabData; CsvData() { FileName = "";

WangPengJu 1557

6、核函数与再生核希尔伯特空间:原理、应用与实践

本文系统介绍了核函数与再生核希尔伯特空间(RKHS)的理论基础、核心性质及其在机器学习和信号处理中的广泛应用。文章从核方法的优势出发,阐述了其在非线性建模、正则化和算法核化方面的独特价值,并深入探讨了正定核、Mercer定理、表示定理等关键理论。通过构建多种标准核与工程专用核,展示了核函数的设计灵活性。结合支持向量回归(SVR)模型与多个MATLAB示例,详细说明了核方法的实际应用流程与操作技巧。最后,总结了核方法的应用领域、未来发展方向及学习实践建议,为读者提供了一套完整的理论与实践指南。

z2a3b4c5d的博客 142

系统盘被 1Panel 撑爆了?一键脚本 3 分钟搞定无损迁移!(1Panel如何快速无损的修改安装目录)

很多用户因默认安装导致 1Panel 面板占满系统盘 😱,本文详解了为何常规快照迁移会失效,并提供了通过**一键自动化脚本**实现无损迁移的完美方案 🛠️。无论你是 NAS 用户还是服务器管理员,都能找到安全扩容的最佳实践。

XiaoqiangClub的博客 1277

Cocos2d-x数据模块教程05:CSV文件解析

通常在一个游戏中会有很多怪物、关卡、技能等数据信息,这些数据不可能在代码里写死,一般都会使用配置文件保存,使用时再加载到内存。 CSV文件编辑起来十分简单,所以常常用来配置游戏的数据信息。本篇要介绍的就是:如何读取CSV文件格式的数据。 【CSVParser解析器下载】 下载地址:https://github.com/shahdza/Cocos_LearningTest/tree/master/CSVParser 【CSV简介】 1、什么是CSV? CSV,即逗号...

翻肚鱼儿的博客 605

Python3实现基于ARIMA模型来预测茅台股票价格趋势

ARIMA(Autoregressive Integrated Moving Average)模型是一种广泛使用的时间序列分析方法,它可以用于对未来的数据进行预测。ARIMA模型由自回归模型(AR模型)、差分整合模型(I模型)和移动平均模型(MA模型)组成,因此也被称为ARIMA(p,d,q)模型。其中,p表示自回归阶数,d表示差分阶数,q表示移动平均阶数。具体来说,ARIMA模型可以通过以下步骤进行建模:数据预处理:对时间序列进行平稳性检验,如果不满足平稳性,则进行差分操作。

m0_64336780的博客 2万+

cocos2dx解析csv数据

使用方法: // on "init" you need to initialize your instance bool HelloWorld::init() {     //////////////////////////////     // 1. super init first     if ( !CCLayer::init() )     {

缥缈的云 专栏 4833

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

[cocos2dx utils] cocos2dx读取,解析csv文件

在我们的游戏中,经常需要将策划的数值配置成csv文件,所以解析csv文件就是一个很common的logic, 例如如下csv文件: 下面是一个基于cocos2dx 2.2.4的实现类: #ifndef __Cell__GCCsvHelper__ #define __Cell__GCCsvHelper__ #include <iostream> #inclu...

weixin_30508241的博客 126

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

游戏开发(五) 之 cocos2dx lua 读取CSV配置表

这一篇说下读取配置表 这一般习惯使用的是csv配置, 游戏中会有各种各样的配置,所以这里就需要一个读取配置表的类. 直接上源码: local XXIO = {} XXIO.allData = {} --数据数组 XXIO.csvPath = "config/" --csv 存储路径 XXIO.Init = function() --初始化 读取所有配置表 local readF...

总会熬出头的 779

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

cocos2dx lua解析csv成lua配置文件,方便程序调用

我很喜欢去读笨木头的文章,简单的说我是笨木头的粉丝!这里读了笨木头的文章之后,引用了 Cocos2d-x Lua 读取Csv文件,更方便的使用数据 这篇文件的数据,写了一个用lua解析csv成lua配置文件,方便程序调用,如果用cocos2dx lua写程序的话,可以这样子来用cha.MissionEntry[1].Index 这里是一段全lua代码: --读取文件内容,返回一个字符串

CDAmber的专栏 2044

cocos2dx Excel表格数据通过csv保存到数据库sqlite

最近需要策划给些数据调试,用Excel比较方便,然后再转换到数据库里程序使用 1 ,首先创建好表格,第一行,每列对应数据库中表名,写好数据后,另存为 .csv格式的文件 TestTable.csv 点击继续 2 . 用火狐的插件SQLite Manager ,注意使用火狐34版本,不然插件导入会有问题 打开要导入的数据库,点击导入import,然后

文艺小青年的专栏 802

Cocos2dx学习第10章(csv 和 json 简单应用)

1.retain 和 release Cocos2dx有一套内存管理机制。retain表示保持引用,以免被释放。一旦对象调用autorelease函数,这个对象就被cocos的内存管理机制盯上了,一旦他没有被认领,那他就会被释放。如下,他就会被内存机制自动释放: // add "HelloWorld" splash screen" sp = Sprite::create("

seaicelin的博客 1646

cocos2d-x(quick-lua)读取csv文件

一、准备一份csv文件 ID,Name,Des,Model ID,名字,描述,图片模型 1,广告,www.benmutou.com,csv.png 2,否认,呵呵,广告什么的,我才不会加,good.png 二、字符串分割函数 function split(str, reps) local resultStrsList = {}; string.gsub(str, '[^

zwcwu31的专栏 1310

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

我的书上或者是我曾经出售的源码里,都有Csv文件的影子。也许是先入为主吧,我工作那会用的最久的配置文件就是Csv,所以我在很多游戏里都会情不自禁地优先选择它。 Csv文件,格式很简单,就是一行一条数据,字段之间用逗号分隔,策划也可以方便地使用Excel进行编辑。Csv格式的文件,解析起来也很简单,所以自己动手写写很快~(小若:我就喜欢拿来主义,你怎么着) 最近在用Lua写游戏,对于技能、怪物等配置

笨木头 1万+

cocos2d-x CSV文件读取 (Excel生成csv文件)

实现类 CCSVParse.h #ifndef __C_CSV_PARSE__ #define __C_CSV_PARSE__ #include "cocos2d.h" #include <vector> using namespace std; class CCSVParse { public: //CCSVParse(void); ...

weixin_33998125的博客 147

cocos2dx读取cvs表

之前做一个项目,把中文数据保存在csv类型的表里面,用的时候根据某行某列读取出来,在此把所使用到的代码贴出来,做个笔记。 1.首先要创建一个文件,把后缀名改为.csv,保存。 2.用Excel打开并写入数据,注意第一个单元格是0行0列 3.把.csv文件放入资源目录下 4.创建CsvHelper文件,把以下代码写入 5.直接对照最下方代码,拿来使用 CsvHelper.h: #ifn

qq_22609555的博客 500

Cocos2dx游戏教程(八):“见缝插针”,UserDefault数据存储与读取

前面已经介绍了前两个场景使用,中间涉及到了几个核心类,菜单,label标签等,同样我们也实现了两个场景的切换和关卡数字的显示。那么我们怎么记录游戏相关的信息呢? 下面我们将走进cocos2dx的数据存储,UserDefault。 一、UserDefault介绍 cocos2dx提供了一个数据存储类UserDefault,可以作为一个轻量级的数据库来使用。它支持五种基本数据bool、int、floa...

小白的专栏 669
上一篇: C#:TexturePacker拆分工具
下一篇: C/C++: 3DES-ECB模式加密,可以与C#和Java互通
胖胖的战士
博客等级 码龄18年 104粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值