代码自动生成工具(一)-Csv读表代码自动生成工具
2017-01-05 13:54
543 查看
之前提到了自定义的Csv格式的表格读取的一个工具类CsvReader
这里我们实现一个可以对任意符合我们人为规定的格式的Csv文件,自动生成其对应的读表代码
本工具需要boost库支持,本人用的是1.55.0
这里首先定义Csv中支持的几种列类型:FieldType:包括有/无符号整数,小数,字符串,子结构
列类型为子结构时,对于子结构信息的定义:ChildStruct:包括字段名,字段类型
整个表格文件,前3行涉及的信息的定义:TableFile:包括表名称,列名称,列类型,注释,是否是主键,是否是数组
Csv文件解析类,读取文件文本内容,按相应配置(命名空间,文件路径等),解析生成相应的CsvFile对象,
传入一个Csv的文件完整路径,调用CsvReader,读取出列名称,列类型,列注释
对于列名称,调用StringTool进行首字母大写
对于列类型,按照自定义Csv格式解析出对应类型或子结构
对于列注释,如果是Utf8,则调用StringTool转换成GBK
具体的代码生成包含两部分功能:
void ParseCsv2LoaderH(const CsvParse& csvParse)
void ParseCsv2LoaderCpp(const CsvParse& csvParse)
void ParseCsv2HelperH(const CsvParse& csvParse)
void ParseCsv2HelperCpp(const CsvParse& csvParse)
传入一个解析好的CsvParse对象,生成具体代码
Loader生成对应的读取代码,读取csv文件的每一行数据,转成相应的数据结构。
Helper生成一个空的辅助类,用于需要对数据重新组织的情况,比如配置中是按某个id列作为主键,存成一个map,提供查找,但是实际逻辑中还需要按某个名称列作为索引,再提供一个map,用于提供按名称查找(或者模糊查找),这时候就需要手动再提供一个新的查找函数,就可以写在helper中
需要生成的代码包括:
main函数涉及两个小功能:
一个是遍历输入参数,解析名命名空间,待处理的csv文件,代码生成路径
一个是迭代每一个待处理的csv文件名,传入CsvParse解析,然后对解析完的结果,逐个生成相应代码
完整的代码,比较长,这里就不贴了
给一个生成后的代码的示例吧:
还是前文的例子:
如上表格,namespace=common.table.csv
生成的头文件如下所示,
放上完整工程的下载链接
工程中的boost库的路径为作者本机的路径,VS编译时请选择Release,重新配置boost库的include路径和lib路径
这里我们实现一个可以对任意符合我们人为规定的格式的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 CsvFile { public: CsvFile(); CsvFile(const CsvFile &other); CsvFile& operator = (const CsvFile &other); ~CsvFile(); 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;// 嵌套的子结构字段名称,类型映射表 };
Csv文件解析类,读取文件文本内容,按相应配置(命名空间,文件路径等),解析生成相应的CsvFile对象,
class CsvParse { public: CsvParse(); ~CsvParse(); bool ParseFile(const std::string& fullPathName); // 解析完毕的csv文件信息列表 std::map<std::string, CsvFile> m_Files; // csv文件解析工具输入参数 public: std::string m_NameSpace; // 自定义命名空间 bool m_ThreadSpecific; // 是否需要线程本地表格数据 std::vector<std::string> m_CsvFileName; // 待处理的csv文件列表 std::string m_LoaderPath; // loader输出cpp代码路径 std::string m_HelperPath; // helper输出cpp代码路径 };
传入一个Csv的文件完整路径,调用CsvReader,读取出列名称,列类型,列注释
对于列名称,调用StringTool进行首字母大写
对于列类型,按照自定义Csv格式解析出对应类型或子结构
对于列注释,如果是Utf8,则调用StringTool转换成GBK
具体的代码生成包含两部分功能:
void ParseCsv2LoaderH(const CsvParse& csvParse)
void ParseCsv2LoaderCpp(const CsvParse& csvParse)
void ParseCsv2HelperH(const CsvParse& csvParse)
void ParseCsv2HelperCpp(const CsvParse& csvParse)
传入一个解析好的CsvParse对象,生成具体代码
Loader生成对应的读取代码,读取csv文件的每一行数据,转成相应的数据结构。
Helper生成一个空的辅助类,用于需要对数据重新组织的情况,比如配置中是按某个id列作为主键,存成一个map,提供查找,但是实际逻辑中还需要按某个名称列作为索引,再提供一个map,用于提供按名称查找(或者模糊查找),这时候就需要手动再提供一个新的查找函数,就可以写在helper中
需要生成的代码包括:
// 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
main函数涉及两个小功能:
一个是遍历输入参数,解析名命名空间,待处理的csv文件,代码生成路径
一个是迭代每一个待处理的csv文件名,传入CsvParse解析,然后对解析完的结果,逐个生成相应代码
完整的代码,比较长,这里就不贴了
给一个生成后的代码的示例吧:
还是前文的例子:
如上表格,namespace=common.table.csv
生成的头文件如下所示,
#ifndef __TestCsvLoader_h__ #define __TestCsvLoader_h__ #include <string> #include <vector> #include <map> namespace common{ namespace table{ namespace csv{ class Test { public: class Struct { public: Struct(); Struct(const Struct &other); Struct& operator = (const Struct &other); Struct& operator = (const std::string &other); unsigned int m_StructId; int m_StructNum; float m_StructFloat; std::string m_StruceName; }; class StructList { public: StructList(); StructList(const StructList &other); StructList& operator = (const StructList &other); StructList& operator = (const std::string &other); unsigned int m_StructId; int m_StructNum; float m_StructFloat; std::string m_StruceName; }; Test(); Test(const Test &other); Test& operator = (const Test &other); unsigned int m_Id1; //测试主键1 int m_Id2; //测试主键2 unsigned int m_Id3; //测试主键3 std::string m_Str; //测试字符串 std::vector<unsigned int> m_UInts; //测试数字列表 float m_Float; //测试数字 Struct m_Struct; //测试子结构 std::vector<StructList> m_StructLists; //测试子结构列表 }; class TestCsvLoader { public: TestCsvLoader() { } ~TestCsvLoader() { } const Test* Get(unsigned int id1, int id2, unsigned int id3) const; const std::map<unsigned int, Test>* Get(unsigned int id1, int id2) const; const std::map<int, std::map<unsigned int, Test> >* Get(unsigned int id1) const; const std::map<unsigned int, std::map<int, std::map<unsigned int, Test> > >& Get() const; bool LoadFile(const char* szPath); bool ReloadFile(const char* szPath); private: std::map<unsigned int, std::map<int, std::map<unsigned int, Test> > > m_Tests; }; } } } #endif
放上完整工程的下载链接
工程中的boost库的路径为作者本机的路径,VS编译时请选择Release,重新配置boost库的include路径和lib路径
相关文章推荐
- 自制工具:CSV代码生成器:自动生成CSV文件对应的C++实体类和字段类型解析代码
- 自制工具:CSV代码生成器:自动生成CSV文件对应的C++实体类和字段类型解析代码
- 开源!开源!我写的Anto.exe C#代码自动生成工具.欢迎下载。。
- [国外]几个代码自动生成工具
- [C#]一步一步开发自己的自动代码生成工具之四:简单三层代码模板实例Model层
- 代码自动生成工具MyGeneration之一(程序员必备工具)
- ibatis - 自动代码生成工具abator 使用介绍
- [C#]一步一步开发自己的自动代码生成工具之三:代码生成引擎
- 代码自动生成工具MyGeneration之二
- 强命名规范与代码自动生成工具
- ibatis代码自动生成工具ibator修改备忘
- ibatis - 自动代码生成工具abator 使用介绍
- [C#]一步一步开发自己的自动代码生成工具之二:SQLServer字段与C#变量的对应转化
- j2ee代码自动生成工具HaivDb4J2ee
- [C#]一步一步开发自己的自动代码生成工具之六:业务层模板
- Nhibernate开发代码工具,自动生成实体类、NHibernate的HBM映射文件和数据访问层的代码
- ibatis - 自动代码生成工具abator 使用介绍(s00n原作)
- 一个好的代码自动生成工具
- DAL是通过代码生成工具自动生成的XSD强类型dataset怎么样把DAL和BLL都独立成项目。
- ibatis - 自动代码生成工具abator 使用介绍