在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
io操作: io.input(filename):指定一个输入流,可以是标准输入stdin,也可以是一个文件路径,返回一个文件句柄; io.output(filename):指定一个输出流,可以是标准输出stdout,也可以是一个文件路径,返回一个文件句柄; io.lines():迭代器,从指定的输入流中读取一行; io.read():从指定的输入流中读取数据,如果不带参数默认读取一行, 参数是"*all"则一次读取整个文件数据; 参数是"*line",读取一行; 参数是"*number",读取一个数字; 参数是number,读取不超过number个字节的数据; io.write(buffer):将数据写入到指定的输出流中; io.open(filename, mode):打开一个文件,如果成功返回一个文件对象,如果失败返回nil; local file = io.open("1.txt", "rw") file:read() file:write("123") file:close() file:seek(where, offset): where的取值: "cur"相对于当前位置进行偏移,"end"相对于结束位置进行偏移,"set"相对于文件开始位置进行偏移。返回值都是当前位置。 io.close(file):关闭一个打开的文件; 实例: 1. 使用io.lines和table.concat,concat比直接使用..连接符号的效率要高很多,特别针对大字符串: local input = io.input("1.txt") local output = io.output("2.txt") t = {} for line in io.lines() do t[#t + 1] = line end local buffer = table.concat(t, "\n") io.write(buffer) io.close(input) io.close(output) 2. 直接使用read,一次读取所有数据: local input = io.input("1.txt") local output = io.output("2.txt") local buffer = io.read("*all") io.write(buffer) io.close(input) io.close(output)
数据文件: lua作为脚步语言的一大特点就是可以将数据存在脚本文件中,然后通过执行“脚本数据文件”,就可以实现导入数据的功能。而且lua的设计的主要用途之一就是针对数据进行描述,在这方面lua进行了大量的优化,因此使用lua脚本来描述数据,比通过文件io操作更加高效: 实例: data.lua,数据描述脚本文件: load_data({"xiaoming", "20", "1000" }) load_data({"xiaoqiang", "18", "2000" }) data_load.lua,数据导入脚本文件,通过定义一个导入方法,就可以将数据导入到当前的运行环境中: t = {} function load_data(data) t[#t + 1] = data end local f = assert(loadfile("./data.lua")); f() for i, data in ipairs(t) do print(i, data[1]) end
序列化: 将一个table中的数据,序列化成json数据: t = { 1, 2, 3, [5] = "df", ["s"] = "212", k = "212", f = {"a", "b", "c"}, j = {{"df", "fd", "d", x = 1, y = 2}, {1, 2,3}} } function serialize(tbl) local buffer_list = {} local arr_list = {} local value_list = {} local value_string = "" local quot = "\"" local colon = ":" local comma = "," local lbrace = "{" rbrace = "}" local lsbracket = "[" rsbracket = "]" local hasArr = false local hasValue = false buffer_list[#buffer_list + 1] = "{" repeat for key, value in ipairs(tbl) do if (not hasArr) then hasArr = true end local typestr = type(value) if typestr == "string" then arr_list[#arr_list + 1] = quot..value..quot elseif typestr == "table" then local subbuf = serialize(value) arr_list[#arr_list + 1] = subbuf else arr_list[#arr_list + 1] = value end end until true if (hasArr) then local keystr = "\"arr\"" local arrstr = table.concat(arr_list, comma); value_list[#value_list + 1] = keystr..":["..arrstr.."]" end repeat for key, value in pairs(tbl) do repeat local keytype = type(key) if keytype == "number" then break end if not hasValue then hasValue = true end local keystr = "\""..key.."\":" local typestr = type(value) if typestr == "string" then value_list[#value_list + 1] = keystr.."\""..value.."\"" elseif typestr == "table" then local subbuf = serialize(value) value_list[#value_list + 1] = keystr..subbuf else value_list[#value_list + 1] = keystr..value end until true end until true if (hasArr or hasValue) then value_string = table.concat(value_list, ",") buffer_list[#buffer_list + 1] = value_string end buffer_list[#buffer_list + 1] = "}" local buffer = table.concat(buffer_list) print(buffer) return buffer end serialize(t) 打印结果: { "arr": [ 1, 2, 3 ], "s": "212", "j": { "arr": [ { "arr": [ "df", "fd", "d" ], "y": 2, "x": 1 }, { "arr": [ 1, 2, 3 ] } ] }, "k": "212", "f": { "arr": [ "a", "b", "c" ] } }
元表: 元表本身是一种table,它可以为其他table定义了一套预定义的操作集合,这类操作集合称为“元方法”。 算术类的元方法: _add:加法;__mul:乘法;__sub:减法;__div:除法;_unm:相反数;__mod:取模;__pow:幂;__concat:连接符; 关系符元方法: __eq:等于;__le:小于等于;__lt:小于; 等于操作符必须是两个对象拥有相同的元方法时候才会被调用,否则会返回false; __index:当在一个对象中无法找到一个key字段时,会返回nil。但如果为其设置了元表,并定义__index元方法,就会返回调用__index的返回值。__index元方法通常是一个函数,但也可以是一个table,如果是一个table,就对该table应用相同的方式进行查找。先检查table中是否存在该字段,如果存在返回该字段的值,如果没有找到,检查table的元表中的__index元方法,以此类推; __newindex:当对对象中的某个字段进行赋值操作时,lua会去搜索元表中是否定义了__newindex元方法,如果存在就调用元方法,反之就会进行一次普通的赋值操作。如果_newindex元方法指向的是一个table,那么相同的操作会应用在table上; lua还提供了两个可以避开__index和__newindex元方法的函数:rawset(t, key, value)和rawget(t, key); 实例: local mt = {} local Point = {} mt.default = { x = 0, y = 0, r = 255, g = 255, b = 255, a = 255 } mt.__add = function (t1, t2) return Point.new(t1.x + t2.x, t1.y + t2.y) end mt.__concat = function (t1, t2) local x = t1.x + t2.x local y = t1.y + t2.y return "x:"..x.." y:"..y end mt.__le = function (t1, t2) return t1.x <= t2.x and t1.y <= t2.y end mt.__eq = function (t1, t2) return t1.x == t2.x and t1.y == t2.y end mt.__tostring = function (t) return "Point x:"..t.x..",y:"..t.y end mt.__index = mt.default // 直接用table来索引,性能更好 -- function (t, k) -- return mt.default[k] -- end mt.__newindex = --mt.default // 用table作为元方法,会把新的字段赋值给table function(t, k, v) rawset(t, k, v) // 跳过元方法,否则会堆栈溢出 end mt.__metatable = "Point metatable" Point.new = function (x, y) assert(type(x) == "number" and type(y) == "number", "Point.new invaild arguments") local pt = {} setmetatable(pt, mt) pt.x = x pt.y = y return pt; end local p1 = Point.new(3, 41) local p2 = Point.new(4, 5) local p3 = p1 + p2 // 调用__add元方法 local str = p1..p2 // 调用__concat元方法 print(p3) // Point x:7,y:46 print(p3.x, p3.y) // 7 46 print(str) // x:7 y:46 print(p1 == p2) // false 调用__eq元方法 print(p3.r) // 255 调用__index元方法,从mt.default表中去查找 print(rawget(p3, "r")) // nil 由于避开了__index元方法,所以返回nil p3.c = 123 // 调用__newindex元方法进行赋值 print(p3.c) // 123 print(p1.c) // nil 因为c字段是赋值给p3的,p1无法访问 print(rawget(p3, "c")) // 123 说明c是直接复制给p3的,没有放在元表上 print(mt.default["c"]) // nil 说明c是直接复制给p3的,没有放在元表上 table的代理: 使用代理的table,可以跟踪对原始table的访问,并可以限制对原始table的控制。
local _t = {x = 2, y = 3, z = 4} local mt = { __index = function (t, k) print("proxy __index", t, k) return t._t[k]; end, __newindex = function (t, k, v) print("proxy __newindex", t, k, v) t._t[k] = v end } function create_proxy (tbl) local proxy = {} proxy._t = tbl; setmetatable(proxy, mt) return proxy; end proxy_t = create_proxy(_t); proxy_t.z = 123 proxy_t.z1 = 456 print(proxy_t.x, proxy_t.y, proxy_t.z, proxy_t.z1) 打印结果: proxy __newindex table: 0x7fb1d2408e10 z 123 proxy __newindex table: 0x7fb1d2408e10 z1 456 proxy __index table: 0x7fb1d2408e10 x proxy __index table: 0x7fb1d2408e10 y proxy __index table: 0x7fb1d2408e10 z proxy __index table: 0x7fb1d2408e10 z1 2 3 123 456
模块: 使用require来导入一个模块,可以是lua模块,也可以是c模块。 require的搜索策略:替换环境变量配置中的?(unix通常是:./?.lua;/usr/local/lua/?.lua;/usr/local/lua/?/init.lua),如果模块名中含有.,将.替换成目录分隔符(unix是/,windows是\)。例如 require "a.b" 会搜索如下路径: lua: /Users/avl-showell/Desktop/lua-5.3.3/test/test1.lua:3: module 'a.b' not found: no field package.preload['a.b'] no file '/usr/local/share/lua/5.2/a/b.lua' no file '/usr/local/share/lua/5.2/a/b/init.lua' no file '/usr/local/lib/lua/5.2/a/b.lua' no file '/usr/local/lib/lua/5.2/a/b/init.lua' no file './a/b.lua' no file '/usr/local/lib/lua/5.2/a/b.so' no file '/usr/local/lib/lua/5.2/loadall.so' no file './a/b.so' no file '/usr/local/lib/lua/5.2/a.so' no file '/usr/local/lib/lua/5.2/loadall.so' no file './a.so' function require (name) if not package.loaded[name] then local loader = findloader(name) if loader == nil then error("unable to load module "..name) end package.loaded[name] = true local res = loader(name) if res ~= nil then package.loaded[name] = res end end return package.loaded[name] end 模块创建方式: local M = {} ...... _G[modulename] = M; package.loaded[modulename] = M return M
|
请发表评论