代码自动生成工具(一)-Csv读表代码自动生成工具

来源:互联网 发布:程序员开发软件 编辑:程序博客网 时间:2024/05/22 23:26

之前提到了自定义的Csv格式的表格读取的一个工具类CsvReader


这里我们实现一个可以对任意符合我们人为规定的格式的Csv文件,自动生成其对应的读表代码

本工具需要boost库支持,本人用的是1.55.0


这里首先定义Csv中支持的几种列类型:FieldType:包括有/无符号整数,小数,字符串,子结构

enum FieldType{FT_int = 0,//整数FT_uint,//整数FT_float,//浮点数FT_string,//字符串FT_struct,//子结构FT_unknow,};

列类型为子结构时,对于子结构信息的定义:ChildStruct:包括字段名,字段类型

class ChildStruct{public:ChildStruct();ChildStruct(const ChildStruct &other);ChildStruct& operator = (const ChildStruct &other);~ChildStruct();std::vector<std::string> m_arrChildName;// 子结构的字段名称std::vector<FieldType> m_arrFieldType;// 子结构的字段类型};

整个表格文件,前3行涉及的信息的定义:TableFile:包括表名称,列名称,列类型,注释,是否是主键,是否是数组

class TableFile{public:TableFile();~TableFile();bool ParseFile(const std::string& pathName);std::string m_strClassName;// 表名称(即需要生成的类名称)std::vector<std::string> m_arrName;// 列名称(原始名称)std::vector<std::string> m_arrType;// 列类型标识字符串std::vector<std::string> m_arrComments;// 列注释std::vector<int> m_arrKey;// 主键列下标std::vector<bool> m_arrIsList;// 列是否是不定长数组(lst)std::vector<FieldType> m_arrFieldType;// 列类型枚举std::map<int, ChildStruct> m_mapChildStruct;// 嵌套的子结构字段名称,类型映射表};

TableFile就一个功能接口:bool ParseFile(const std::string& pathName);

传入一个Csv的文件完整路径,调用CsvReader,读取出列名称,列类型,列注释

对于列名称,调用StringTool进行首字母大写

对于列类型,按照自定义Csv格式解析出对应类型或子结构

对于列注释,如果是Utf8,则调用StringTool转换成GBK


具体的代码生成包含两部分功能:

void ParseTable2H(const char* outFilePath, const TableFile& inTableFile)

void ParseTable2CPP(const char* outFilePath, const TableFile& inTableFile)

传入一个解析好的TableFile对象,以及输出的.h/.cpp文件路径,生成具体代码


需要生成的代码包括:

// 1、头文件:map,vector等//// 2、命名空间(由程序运行参数决定)//// 3、每个子结构:class XXX {...};// 包括:// 构造:XXX() {...}// 拷贝构造:XXX(const XXX &other) {...}// 赋值:XXX& operator = (const XXX &other) {...}// 赋值:XXX& operator = (const std::string &other) {...}// 子结构的各个字段罗列//// 4、表结构:class XXX {...};// 包括:// 构造:XXX() {...}// 拷贝构造:XXX(const XXX &other) {...}// 赋值:XXX& operator = (const XXX &other) {...}// 表结构的各个字段罗列//// 5、表结构对应的管理器类:class XXXTable {...};// 包括:// 构造:XXXTable();// 析构:~XXXTable();// 获取表格数据:Get//     对于3个主键的,则生成://     const XXX* Get(k1, k2, k3){...}//     const std::map<k3type, XXX>* Get(k1, k2){...}//     const std::map<k2type, std::map<k3type, XXX> >* Get(k1){...}//     const std::map<k1type, std::map<k2type, std::map<k3type, XXX> > >& Get(){...}//     对于2个主键的则生成://     const XXX* Get(k1, k2);//     const std::map<k2type, XXX>* Get(k1);//     const std::map<k1type, std::map<k2type, XXX> >& Get();//     对于1个主键的则生成://     const XXX* Get(k1);//     const std::map<k1type, XXX>& Get();//     对于没有主键的,那么按照数组处理,生成://     const XXX* Get(index);//     const std::vector<XXX>& Get();// 表格加载:bool Load(const wchar_t* pFilePathName);// 表格管理器的成员:// 表格数据列表:m_XXXs,有主键的则为map,没有主键的则为vector//// 6、如果启用thread_specific_ptr,生成boost::thread_specific_ptr<XXXTable> ptr


main函数涉及两个小功能:

一个是遍历指定文件夹,获取该文件夹下的所有Csv文件(本工具没有递归,不搜子文件夹):windows下用findfirst,findnext,findclose;linux下用opendir,readdir,closedir

一个是解析exe传入参数,目前支持4个参数:包括输入文件(即Csv文件目录),输出文件(即代码文件目录),生成的代码指定namespace,生成的代码是否启用线程本地存储(即是否使用boost库提供的thread_specific_ptr来管理表格对象)


完整的代码,比较长,这里就不贴了


给一个生成后的代码的示例吧:

还是前文的例子:


如上表格,启用thread_specific_ptr,namespace=common.table

生成的头文件如下所示,

#ifndef __Test_h__#define __Test_h__#include <map>#include <vector>#include <boost/thread/tss.hpp>namespace common{namespace table{class TestStruct{public:TestStruct();TestStruct(const TestStruct &other);TestStruct& operator = (const TestStruct &other);TestStruct& operator = (const std::string &other);unsigned int m_StructId;int m_StructNum;float m_StructFloat;std::string m_StruceName;};class TestStructList{public:TestStructList();TestStructList(const TestStructList &other);TestStructList& operator = (const TestStructList &other);TestStructList& operator = (const std::string &other);unsigned int m_StructId;int m_StructNum;float m_StructFloat;std::string m_StruceName;};class Test{public:Test();Test(const Test &other);Test& operator = (const Test &other);unsigned int m_Id1;//测试主键1int m_Id2;//测试主键2unsigned int m_Id3;//测试主键3std::string m_Str;//测试字符串std::vector<unsigned int> m_UInts;//测试数字列表float m_Float;//测试数字TestStruct m_Struct;//测试子结构std::vector<TestStructList> m_StructLists;//测试子结构列表};class TestTable{public:TestTable();~TestTable();const Test* Get(unsigned int Id1, int Id2, unsigned int Id3);const std::map<unsigned int, Test>* Get(unsigned int Id1, int Id2);const std::map<int, std::map<unsigned int, Test> >* Get(unsigned int Id1);const std::map<unsigned int, std::map<int, std::map<unsigned int, Test> > >& Get();bool Load(const char* pFilePathName);private:std::map<unsigned int, std::map<int, std::map<unsigned int, Test> > > m_Tests;};typedef boost::thread_specific_ptr<TestTable> TestTablePtr;extern TestTablePtr g_TestTableMgr;}}#endif

放上完整工程的下载链接


下载内容包括(发的文本对不齐,还是发图片吧)


工程中的boost库的路径为作者本机的路径,VS编译时请选择Release,重新配置boost库的include路径和lib路径

Test.csv文件为了兼容linux上传的是UTF-8(不带BOM)格式,windows下直接用txt打开可见,Excel打开前请先转换格式

linux环境请支持zh_CN.GB18030



0 0
原创粉丝点击