lua与配置文件

lua的一项重要用途就是作为一种配置语言(configuration language)

目前,我们常用的配置文件格式有XMLini, XML层次分明,但其缺点就是写起来太繁杂,对一些关键字如<>之类的处理比较特殊。而ini呢,配置不够灵活,只有简单的段-键-值模式,对于一些多层结构的配置,或者一些列表类型的配置,就显得力不从心了,往往需要编码人员自己分割字符串。
Lua脚本非常简洁清晰,是非常适合做配置文件的,无论是映射表型配置,还是列表型配置,还是简单的键值配置,lua都可以完全胜任。而且lua格式清新简洁,一看就懂。

下面的代码主要是读变量和table
mycon.lua

1
2
3
4
5
6
7
--my config 

width = 300
height = 400

luat_Test1={a=123, b=456, c=789}
luat_Test2={123, 456, 789}

这里说个题外话,Lua不会根据一个范围的值来创建表,而是根据设定的单个值来创建表内容,比如:

1
2
textTable = {}
textTable[2000] = "hello 2000!"

这里虽然会生成许多未使用的Key,但不必担心这个方法会牺牲任何表的存储空间。
main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include<stdio.h>  

//如不用extern会出现连接错误,编译成了C++文件
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}

#pragma comment(lib, "lua5.1.lib")

void ReadVariable (lua_State *L,int *width,int *height){
lua_getglobal(L,"width"); //获得Lua中变量的值,将其放入栈中
lua_getglobal(L,"height");

if(!lua_isnumber(L,-2)) //栈顶为-1,然后依次减少
luaL_error(L,"`width' should be a number\n");

if(!lua_isnumber(L,-1))
luaL_error(L,"`height' should be a number\n");
*width = (int)lua_tonumber(L,-2); //将栈顶元素转化为数字
*height = (int)lua_tonumber(L,-1);
printf("width is %d ,height is %d\n\n",*width,*height);
}

static void ReadTableFromItem(lua_State *L, const char* lpszTableName, const char* lpszTableItem)
{
lua_getglobal(L, lpszTableName);

lua_pushstring(L, lpszTableItem);//首先把元素的名字压入栈顶
lua_gettable(L, -2);//值会放在栈顶,同时刚才压入的元素名字被弹出
printf("%s.%s=%d\n", lpszTableName, lpszTableItem, (int)lua_tonumber(L, -1));
lua_pop(L, 2);
}

static void ReadTableFromIndex(lua_State *L, const char* lpszTableName, int index)
{
lua_getglobal(L, lpszTableName);
lua_rawgeti(L, -1, index);//获得第一个元素
printf("%s[%d]=%d\n", lpszTableName, index, (int)lua_tonumber(L, -1));
lua_pop(L, 2);
}

static void EnumTableItem(lua_State *L, const char* lpszTableName)
{
lua_getglobal(L, lpszTableName);
int it = lua_gettop(L);
lua_pushnil(L);
printf("Enum %s:", lpszTableName);
while(lua_next(L, it))//用lua_next可以遍历这个数组
{
printf(" %d", (int)lua_tonumber(L, -1));
lua_pop(L, 1);
}
printf("\n\n");
lua_pop(L, 1);
}

int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("param error!\n");
return 0;
}

char *filename = argv[1];

lua_State *L = lua_open();
luaL_openlibs(L); //新版本库添加的方法
if(luaL_loadfile(L,filename) || lua_pcall(L,0,0,0)){
luaL_error(L,"loadfile error! %s \n",lua_tostring(L,-1));
}

int w=1,h=2;
ReadVariable(L,&w,&h);

ReadTableFromItem(L, "luat_Test1", "a"); // 等价与lua代码:print(luat_Test1.a)
ReadTableFromItem(L, "luat_Test1", "b");
ReadTableFromItem(L, "luat_Test1", "c");
EnumTableItem(L, "luat_Test1"); // 枚举Table

ReadTableFromIndex(L, "luat_Test2", 1); // 等价与lua代码:print(luat_Test1[1])
ReadTableFromIndex(L, "luat_Test2", 2);
ReadTableFromIndex(L, "luat_Test2", 3);
EnumTableItem(L, "luat_Test2");
getchar();
return 0;
}

关于配置文件安全的问题,一般会将这些lua文件进行加密。

excel转lua

配置文件多数以excellua的方式配置,网上也有很多相关工具。例如用xlrd

多维数组

用[]表示数组,如

  • [123456,123457]表示两个物品
  • [1,1001001,1]表示物品的类型、code、数量
  • 如果要配置多种数据,可以使用json

    多key配置

    这个要写个配置文件,明确是用哪些字段作key

    时间

    可以按这个格式:

    2019-1-1 1:00:00
    再根据需求转时间戳。


Todos los caminos llevan a Roma.