八、Lua脚本详解—— 超详细操作演示!

发布时间:2024年01月05日

数据库系列文章:

关系型数据库:


非关系型数据库:

八、Lua脚本详解

8.1 Lua 简介

????Lua 是一个由标准 C 语言 开发的、开源的、可扩展的轻量级的弱类型的解释型脚本语言, 是 于 1993 年由 巴西里约热内卢天主教大学的三人研究小组使用标准 C 语言开发。

????Lua 的官网 为: https://www.lua.org/

Lua 是一门 脚本语言,和 ShellPython 是同一种类型。

用的最多的是 Unity 手游,做 热更新 方案;Nginx 也有应用。

8.2 Linux 系统的Lua

8.2.1 Lua 下载

????若要使用 Lua 则需要先从官网下载其源码并安装。

在这里插入图片描述

8.2.2 Lua 安装

????先将下载好的 Lua 源码上传到 Linux ,然后再进行安装。

??(1)解压

????将Lua 源码解压到 /opt/apps 目录。

tar -zxvf lua-5.4.6.tar.gz -C /opt/apps/

在这里插入图片描述

????进入到 /opt/apps 下的 lua 目录可以看到编译用的 Makefile 文件 及 源码目录 src

在这里插入图片描述

??(2)安装gcc

????由于 Lua 是由 C/C++ 语言编写的,所以对其进行 编译 就必须要使用相关编译器。对于 C/C++ 语言的编译器,使用最多的是 gcc

yum -y install gcc gcc-c++

在这里插入图片描述

??(3)编译

????执行编译命令 make linux test

# test 测试输出版本号
make linux test

??(4)安装

make install

在这里插入图片描述

????安装完毕后,可以通过 lua -v 查看版本号,与前面 make linux test 中最后显示的结果是相同的。

在这里插入图片描述

如果 lua -v 显示的还是老版本,reboot 重启一下 Linux 系统就好了。

8.2.3 Hello World

??(1)两种交互模式

????Lua 为用户提供了两种交互模式:命令行模式脚本文件模式

A、命令行模式

????该模式是,直接在命令行中输入语句,回车即可看到运行结果。

在这里插入图片描述

????在任意目录下使用 lua 命令进入 lua 命令行模式,在其中输入语句后回车即可运行显示出结果。使用 Ctrl + C 退出模式。

????需要注意, lua 对语句后的 分号要求 不是 强制性的,有没有都行

B、脚本文件模式

????该模式是先要编写脚本文件,然后再使用 lua 命令运行文件。

????例如直接创建一个名称为 hello.lua 的文件,文件中就写一名 print() 语句即可。

在这里插入图片描述

????然后 直接运行lua 脚本文件” 即可看到结果。

lua hello.lua

在这里插入图片描述

??(2)两种脚本运行方式

????对于脚本文件的运行有两种方式。

  • 一种是上面的 lua 命令 方式,
  • 还有一种是 可执行文件 方式。可执行文件方式是,将 lua 脚本文件直接修改为 可执行文件 运行。

????下面就使用第二种方式来运行。

A、修改脚本文件内容

????在脚本文件第一行增加 #!/usr/bin/lua ,表示当前文件将使用 /usr/bin/lua 命令来运行。

#!/usr/bin/lua

在这里插入图片描述

B、修改脚本文件权限

chmod 755 hello.lua

????为脚本文件赋予 可执行权限

C、运行

????直接使用文件名即可运行。
在这里插入图片描述

8.3 Win 系统的Lua

????这里要安装的是在 Windows 系统中 Lua 的运行环境。最常用的为 SciTE

????SciTE 是一款 Lua 脚本 测试编辑器,提供 Lua 的编辑运行环境。其官方下载地址为: https://github.com/rjpcomputing/luaforwindows/releases 。 下载完直接运行 exe 文件安装。
在这里插入图片描述

????SciTE 提供了两种运行方式:命令行窗口运行方式 与 Lua 脚本的编辑运行环境

在这里插入图片描述
在这里插入图片描述

????除了SciTE ,还有像 LuaDistLuaRocks 等。

8.4 Lua 脚本基础

8.4.1 注释

????Lua行注释 为两个连续的减号段注释--[[ 开头,以 --]] 结尾

????不过,在 调试过程 中如果想 临时取消 段注释,而直接将其标识删除,这样做其实并不好。因为有可能还需要再添加上。而段注释的写法相对较麻烦。

  • 所以, Lua 给出了一种简单处理方式:在开头的 --[[再加一个减号,即可使段注释不起作用。其实就是使两个段注释标识变为了两个行注释。
--~ 行注释,(快捷键为 Ctr + Q)
-- 行注释,(波浪号 ~ ,为快捷键自动生成的)

--[[段注释
print("Hello, Lua")
--]]

---[[取消段注释
print("Hello, Lua")
--]]
8.4.2 数据类型

????Lua 中有 8 种 类型,分别为: nilbooleannumberstringuserdatafunctionthreadtable

  • 通过 type() 函数可以查看一个数据的类型,例如, type(nil) 的结果为 niltype(123) 的结果为 number

在这里插入图片描述

-- string 演示
str1 = "中国"
str2 = '北京'
str3 = [[深圳
广州
上海]]

print(str1) 
print(str2)
print(str3)

--[[输出:
中国
北京
深圳
广州
上海
--]]
8.4.3 标识符

????程序设计语言中的标识符主要包含 保留字、变量、常量、方法名、函数名、类名 等。Lua 的标识符由 字母、数字 与 下划线 组成,但 不能以数字开头Lua大小写敏感的

??(1)保留字

????Lua 常见的保留字共有 22 个。不过,除了这 22 个外, Lua 中还定义了很多的 内置全局变量 ,这些内置全局变量的一个共同特征是,以下划线开头后跟全大写字母 。所以我们在定义自己的标识符时不能与这些保留字、内置全局变量重复

在这里插入图片描述

??(2)变量

????Lua 是弱类型语言变量 无需类型声明可直接使用。变量分为 全局变量局部变量。Lua 中的变量 默认都是全局变量,即使声明在语句块或函数里。全局变量一旦声明,在当前文件中的(声明后)任何地方 都可访问。局部变量 local 相当于 Java 中的 private 变量,只能在声明的语句块中使用。

-- 局部变量
local x = 3

-- 定义一个函数
function f()
	-- 全局变量
	y = 5
	-- 再定义一个局部变量
	local z = 8
	-- 访问局部变量
	print("x = "..x);
end

-- 访问函数
f(); 				 -- 输出 x = 3
-- 访问全局变量
print("y = "..y)	 -- 输出 y = 5
-- 访问局部变量
print("z = "..z)	 -- 报错,z 为局部变量

??(3)动态类型

????Lua 是 动态类型语言变量的类型 可以随时改变,无需声明

y = 5
print("y = "..y)	 -- 输出 y = 5
y = "北京"
print("y = "..y)	 -- 输出 y = 北京
8.4.4 运算符

????运算符是一个特殊的符号,用于告诉解释器执行特定的 数学逻辑运算。Lua 提供了以下几种运算符类型:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 其他运算符

??(1)算术运算符

????下表列出了 Lua 语言中的常用算术运算符,设定 A 的值为 10B 的值为 20

在这里插入图片描述

注意,

  • SciTE 对 Lua 支持的目前最高版本为 5.1 ,而整除运算符 // 需要在 Lua5.3 版本以上,所以当前 SciTE 中无法看到效果。
  • 命令行模式 中,直接输入变量名 回车,即相当于 print() 函数输出该变量。

??(2)关系运算符

????下表列出了 Lua 语言中的常用关系运算符,设定 A 的值为 10B 的值为 20

在这里插入图片描述

??(3)逻辑运算符

????注意, Lua 系统将 falsenil 作为 ,将 true非nil 作为 即使是 0 也是

????下表列出了Lua 语言中的常用 逻辑运算符,设定 A 的值为 trueB 的值为 false

在这里插入图片描述

??(4)其他运算符

????下表列出了 Lua 语言中的 连接运算符计算 字符串 长度 的运算符:

在这里插入图片描述

str = "abcdefg"
print(#str) 	 -- 输出 7
8.4.5 函数

????Lua 中函数的定义是以 function 开头,后跟 函数名参数列表,以 end 结尾。其 可以没有返回值,也可以一次返回多个值

??(1)固定参函数

????Lua 中的函数在调用时与 Java 语言中方法的调用是不同的,其 不要求实参的个数必须与函数中形参的个数相同

  • 如果实参个数少于形参个数,则系统自动使用 nil 填充;
  • 如果实参个数多于形参个数,多出的将被系统 自动忽略
-- 定义一个普通函数,包含两个形参
function f(a, b)
	print(a, b)
end

-- 无实参传递
f()					-- 输出:nil	nil

-- 传递一个实参
f(10)				-- 输出:10 	nil

-- 传递两个实参
f(10, 20)			-- 输出:10 	20

-- 传递三个实参
f(10, 20, 30)		-- 输出:10 	20

??(2)可变参函数

????在函数定义时不给出具体形参的个数,而是使用 三个连续的点号。在函数调用时就可以向该函数传递任意个数的参数,函数可以全部接收。

-- 定义一个可变参函数
function f(...)
	local a,b,c,d = ...
	print(a, b, c, d)
	--print(...) 	-- 可以全部输出
end

-- 传递三个实参
f(10, 20, 30)					-- 输出:10 20	30	nil

-- 传递四个实参
f(10, 20, 30, 40)				-- 输出:10	20	30	40

-- 传递五个实参
f(10, 20, 30, 40, 50)			-- 输出:10	20	30	40

??(3)可返回多个值

????Lua 中的函数一次可以返回多个值,但需要有多个变量来同时接收

-- 定义一个普通函数,返回两个值
function f(a, b)
	local sum = a + b
	local mul = a * b
	return sum, mul;
end

-- 一次性接收两个值
m, n = f(3, 5)
print(m, n)					-- 输出:8 15

??(4)函数作为参数

????Lua 的函数中,允许 函数 作为参数。而作为参数的函数,可以是已经定义好的 普通函数,也可以是匿名函数

-- 定义两个普通函数
function sum(a, b)
	return a + b
end

function mul(a, b)
	return a * b
end

-- 定义一个函数,其参数为另一个参数
function f(m, n, fun)
	local result = fun(m, n)
	print(result)
end

-- 调用
f(3, 5, sum)					-- 输出:8
f(3, 5, mul)					-- 输出:15

-- 匿名函数调用
f(3, 5, function (a, b)
			return b - a;
		end
);								-- 输出:2
8.4.6 流程控制语句

????Lua 提供了 if 作为 流程控制语句

??(1)if 语句

????Lua 提供了 if...then 用于表示条件判断,其中 if 的判断条件可以是 任意表达式。 Lua 系统将 falsenil 作为,将 true非nil 作为,即使 0 也是

a = 5
if(a > 0) then
	print("num > 0")
else
	print("num <= 0")
end

-- 输出: num > 0

????需要注意,Lua 中的 if 语句的判断条件 可以使用小括号括起来,也可以不使用

??(2)if 嵌套语句

????Lua 中提供了专门的关键字 elseif 来做 if 嵌套语句注意,不能使用 elseif 两个关键字的联用形式 ,即不能使用 else if 来嵌套 if 语句。

a = 5
if(a > 0) then
	print("num > 0")
elseif a == 0 then
	print("num = 0")
else
	print("num < 0")
end
8.4.7 循环控制语句

????Lua 提供了四种循环控制语句while...do 循环、 repeat...until 循环、数值 for 循环,及 泛型 for 循环。同时, Lua 还提供了 breakgoto 两种循环流程控制语句

??(1)while … do

????只要 while 中的 条件成立 就一直循环

a = 3
while a>0 do
	print(a)
	a = a - 1    -- 注意:这里没有a--
end

输出:
3
2
1

??(2)repeat … until

????until 中的 条件成立了,循环就要 停止

a = 3
repeat
	print(a)
	a = a - 1    -- 注意:这里没有a--
until a <= 0

输出:
3
2
1

??(3)数值 for

????这种 for 循环只参用于循环变量数值型 的情况。其语法格式为:

for var=exp1, exp2, exp3 do
	循环体
end

????var 为指定的 循环变量exp1 为 循环 起始值exp2 为 循环 结束值exp3 为 循环 步长

  • 步长可省略不写,默认1
  • 每循环一次,系统内部都会做一次当前循环变量 var 的值与 exp2 的比较,如果 var 小于等于 exp2 的值,则继续循环,否则结束循环。

例如:

for i = 10, 50, 20 do
	print(i)
end

输出:
10
30
50

??(4)泛型 for

????泛型 for 用于遍历 table 中的所有值,其需要与 Lua 的 迭代器 联合使用。后面 table 学习时再详解。

??(5)break

????break 语句可以提前终止循环。其只能用于循环之中。

for i = 1, 9 do
	print(i)
	if i == 3 then
		break
	end
end

输出:
1
2
3

??(6)goto (不建议使用,不然可能使代码杂乱无章)

????goto 语句可以将执行流程 无条件地跳转 到指定的标记语句处开始执行,注意,是开始执行,并非仅执行这一句,而是从这句开始后面的语句都会重新执行。当然,该标识语句在第一次经过时也是会执行的,并非是必须由 goto 跳转时才执行。

????语句标记使用一对双冒号括起来,置于语句前面。goto 语句可以使用在循环之外。

function f(a)
	::flag:: print("=========")
	if a > 1 then
		print(a)
		a = a - 1
		goto flag
	end
end

f(5)

输出:
=========
5
=========
4
=========
3
=========
2
=========

????注意,Lua5.1不支持 双冒号 的语句标记。

8.5 Lua 语法进阶

8.5.1 table

??(1)数组

????使用 table 可以定义 一维、二维、多维数组。不过,需要注意, Lua 中的数组索引是从 1 开始的,且 无需声明数组长度,可以随时增加元素。当然,同一数组中的 元素可以是任意类型

-- 定义一个一维数组
cities = {"北京", "上海", "广州"}
cities[4] = "深圳"

for i=1, 4 do
	print("cities["..i.."]="..cities[i])
end

输出:
cities[1]=北京
cities[2]=上海
cities[3]=广州
cities[4]=深圳

-- 声明一个二维数组
arr = {} 			-- 必须声明空数组
for i= 1, 3 do
	arr[i] = {}		-- 必须声明空数组
	for j = 1, 2 do
		arr[i][j] = i * j
		print(arr[i][j])
	end
end

输出:
1
2
2
4
3
6

??(2)map

????使用 table 也可以定义出类似 mapkey-value 数据结构。其可以定义 table 时直接指定 key-value ,也可单独指定 key-value 。而访问时,一般都是通过 tablekey 直接访问,也可以数组索引方式来访问,此时的 key 即为索引

例 1 :

-- 定义一个map
emp  = {name = "张三", age = "23", depart = "销售部"}

-- 通过下标方式操作
emp["gender"] = "男"
print(emp["name"])				-- 输出:张三
print(emp["gender"])			-- 输出:男

-- 点号方式操作 (推荐)
emp.office = "2nd floor"
print(emp.age)					-- 输出:23
print(emp.office)				-- 输出:2nd floor

例 2 :

a = "xxx"
b = 3
c = 5

-- 定义一个map,其key为表达式(需要用方括号括起来)
arr = {
	["emp_"..a] = true,
	["hi"] = 123,
	[b + c] = "hello",
}

print(arr.emp_xxx)				-- 输出:true
-- print(arr.8)   -- 报错
print(arr.hi)					-- 输出:123
print(arr[8])					-- 输出:hello

??(3)混合结构

????Lua 允许将数组与 key-value 混合在同一个 table 中进行定义。 key-value 不会占用数组的数字索引值

emp  = {"北京", name = "张三", "上海", age = "23", "广州", depart = "销售部", "深圳"}

print(emp[1])					-- 输出:北京
print(emp[2])					-- 输出:上海
print(emp[3])					-- 输出:广州
print(emp[4])					-- 输出:深圳

常见使用方法:

-- 定义一个数组,map 为混合结构
emp = {
	{name="张三", age=23},
	{name="李四", age=24},
	{name="王五", age=25},
	{name="赵六", age=26},
}

for i = 1, 4 do
	print(emp[i].name.." : "..emp[i].age)
end

输出:
张三 : 23
李四 : 24
王五 : 25
赵六 : 26

??(4)table 操作函数

????Lua 中提供了对 table 进行操作的函数

A、table.concat()

函数table.concat (table [, sep [, start [, end]]]):
解析】该函数用于将指定的 table 数组元素 进行 字符串连接。连接从 start 索引位置到 end 索引位置的所有数组元素, 元素间使用指定的分隔符 sep 隔开。 如果 table 是一个混合结构,那么这个连接与 key-value 无关,仅是连接数组元素

emp  = {"北京", name = "张三", "上海", age = "23", "广州", depart = "销售部", "深圳"}

print(table.concat(emp, ","))  -- 输出:北京,上海,广州,深圳
print(table.concat(emp, ",", 2, 3))  -- 输出:上海,广州

B、table.unpack()

函数table.unpack (table [, i [, j]])
解析拆包。该函数返回指定 table数组 中的从第 i 个元素到第 j 个元素值。 ij 是可选的,默认 i1j 为数组的最后一个元素。 Lua5.1 不支持该函数。

arr = {"bj", "sh", "gz", "sz"}

table.unpack(arr)  			 -- 输出:bj	sh	gz	sz
table.unpack(arr, 2, 3) 	 -- 输出:sh	gz

-- 也可以使用变量接收
a, b, c, d = table.unpack(arr)

C、table.pack()

函数table. pack (...)
解析】打包。该函数的参数是一个可变参,其可将指定的参数打包为一个 table 返回。这个返回的 table 中具有一个属性 n ,用于表示该 table 包含的 元素个数。 Lua5.1 不支持该函数。

t = table.pack("apple", "banana", "peach")
table.concat(t, ",") 			-- 输出:apple,banana,peach

D、table.maxn()

函数table.maxn(table)
解析】该函数返回指定 table 的数组中的 最大索引值,即数组包含元素的个数

emp  = {"北京", name = "张三", "上海", age = "23", "广州", depart = "销售部", "深圳"}

print(table.concat(emp, ","))  -- 输出:北京,上海,广州,深圳

print(table.maxn(emp))		   -- 输出:4

E、table.insert()

函数table.insert (table, [pos,] value):
解析】该函数用于在指定 table 的数组部分指定位置 pos 插入值为 value 的一个元素 。 其后的元素会被后移 。 pos 参数可选 默认为数组部分末尾 。

cities = {"北京", "上海", "广州"}

table.insert(cities, 2, "深圳")
table.insert(cities, "天津")

print(table.concat(cities, ",")) -- 输出:北京,深圳,上海,广州,天津

F、table.remove()

函数table.remove (table [, pos])
解析】该函数用于 删除并返回 指定 table 中数组部分位于 pos 位置的元素 。 其后的元素会被前移pos 参数可选默认删除数组中的最后一个元素

cities = {"北京", "上海", "广州", "深圳", "天津"}

table.remove(cities, 2)
table.remove(cities)

print(table.concat(cities, ",")) -- 输出:北京,广州,深圳

G、table.sort()

函数table. sort(table [,fun(a,b)])
解析】该函数用于对指定的 table 的数组元素进行 默认 升序排序,也可按照指定函数 fun(a,b)指定的规则进行排序。 fun(a,b) 是一个用于比较 ab 的函数, ab 分别代表数组中的两个相邻元素。

cities = {"bj北京", "sh上海", "gz广州", "sz深圳", "tj天津"}

table.sort(cities, function(a, b)     -- 降序
						return a > b  -- 如果相邻的两个为真,保持原来的队形
				   end
)

print(table.concat(cities, ",")) -- 输出:tj天津,sz深圳,sh上海,gz广州,bj北京

注意

  • 如果 arr 中的元素既有 字符串 又有 数值型 ,那么对其进行排序会 报错
  • 如果数组中多个元素相同,则其相同的多个元素的排序结果不确定,即这些元素的索引谁排前谁排后,不确定
  • 如果数组元素中包含 nil ,则排序会 报错
8.5.2 迭代器

????Lua 提供了两个迭代器 pairs(table)ipairs(table) 。这两个迭代器通常会应用于 泛型 for 循环中,用于遍历指定的 table 。这两个迭代器的不同是:

  • ipairs(table) :仅会迭代指定 table 中的 数组元素
  • pairs(table):会迭代 整个 table 元素 ,无论是 数组元素,还是 key-value
emp  = {"北京", name = "张三", "上海", age = "23", "广州", depart = "销售部", "深圳"}

-- 遍历emp中的所有数组元素
for i, v in ipairs(emp) do
	print(i, v)
end
--[[输出:
1	北京
2	上海
3	广州
4	深圳
--]]

-- 遍历emp中的所有元素
for k, v in pairs(emp) do
	print(k, v)
end
--[[输出:
1	北京
2	上海
3	广州
4	深圳
depart	销售部
name	张三
age	23
--]]
8.5.3 模块

????模块是 Lua 中特有的一种数据结构。 从 Lua 5.1 开始, Lua 加入了标准的 模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口 的形式在其他地方调用,有利于代码的重用降低代码耦合度

????模块文件主要由 table 组成。在 table 中添加相应的变量函数,最后文件返回table 即可。如果其它文件中需要使用该模块,只需通过 require 将该 模块导入 即可。

??(1)定义一个模块

????模块 是一个 lua 文件,其中会包含一个 table 。一般情况下该文件名与该 table 名称相同,但其 并不是必须的

例如: 定义rectangle模块, 创建一个rectangle.lua 文件

-- 声明一个模块
rectangle = {}

-- 为模块添加一个变量
rectangle.pi = 3.14

-- 为模块添加函数(求周长)
function rectangle.perimeter(a, b)
	return (a + b) * 2
end

-- 以匿名函数方式为模块添加一个函数(求面积)
rectangle.area = function(a, b)
	return a * b
end


-- ================= 定义与模块无关的内容===============
-- 定义一个全局变量
goldenRatio = 0.618

-- 定义一个局部函数(求圆的面积)
local function circularArea(r)
	return rectangle.pi * r * r
end

-- 定义一个全局函数(求矩形中最大圆的面积)
function maxCircularArea(a, b)
	local r = math.min(a, b)
	return circularArea(r / 2)
end

return rectangle

??(2)使用模块

????这里要用到一个函数 require("文件路径")),其中文件名是 不能写 .lua 扩展名的。该函数可以将指定的 lua 文件静态导入(合并为一个文件)。不过需要注意的是,该函数的使用可以省略小括号,写为 require"文件路径"

-- 导入一个模块
require "rectangle"

-- 访问模块的属性,调用模块的函数
print(rectangle.pi)						-- 输出:3.14
print(rectangle.perimeter(3, 5))		-- 输出:16
print(rectangle.area(3, 5))				-- 输出:15

????require() 函数是有返回值的,返回的就是模块文件最后 returntable 。可以使用一个变量接收该 table作为模块的别名,就可以 使用 别名 来访问模块了。

-- 导入一个模块
rect = require "rectangle"

-- 访问模块的属性,调用模块的函数
print(rect.pi)						-- 输出:3.14
print(rect.perimeter(3, 5))			-- 输出:16
print(rect.area(3, 5))				-- 输出:15


-- 访问模块中与模块无关的内容
print(goldenRatio)						-- 输出:0.618
print(maxCircularArea(4, 5))			-- 输出:12.56
-- print(circularArea(2))	-- 报错,局部的不能访问

??(3)再看模块

????模块文件中一般定义的 变量函数 都是模块 table 相关内容,但也可以定义其它与 table 无关的内容。这些 全局变量与函数 就是 普通的全局变量与函数与模块无关,但会随着模块的导入而同时导入。所以在使用时可以直接使用,而无需也不能添加模块名称。

8.5.4 元表和元方法

????元表,即 Lua 中普通 table元数据表,而 元方法 则是元表中定义的普通表的默认行为。Lua 中的每个普通 table 都可为其定义一个元表,用于扩展该普通 table 的行为功能。例如,

  • 对于 table 与数值相加的行为, Lua 中是没有定义的,但用户可通过为其指定元表来扩展这种行为;
  • 再如,用户访问不存在的 table 元素, Lua 默认返回的是 nil ,但用户可能并不知道发生了什么。此时可以通过为该 table 指定元表来扩展该行为:给用户提示信息,并返回用户指定的值。

??(1)重要函数

元表中有两个重要函数

  • setmetatable(table, metatable) 将 metatable 指定为普通表 table 的元表。
  • getmetatable(table) 获取指定普通表 table 的元表。

??(2)__index 元方法
??(3)__newindex 元方法
??(4)运算符 元方法
??(5)__tostring 元方法
??(6)__call 元方法
??(7)元表单独定义

8.5.5 面向对象

??(1)简单对象的创建
??(2)类的创建

8.5.6 协同线程与协同函数

??(1)协同线程
??(2)协同函数

8.5.7 文件IO

??(1)常用静态函数

A、io.open()

格式io.open (filename [, mode])
解析】以 指定模式 打开指定文件,返回要打开文件的 句柄,就是一个对象(后面会讲 Lua 中的对象)。其中模式 mode三种,但同时还可配合两个符号使用:

  • r只读,默认模式
  • w只写,写入内容会覆盖文件原有内容
  • a只写,以追加方式写入内容
  • +增加符,在 r+w+a+ 均变为了 读写
  • b二进制表示符。如果要操作的文件为二进制文件,则需要变为 rbwbab

B、io.input()

格式io.input (file)
解析】指定要读取的文件。

C、io.outout()

格式io.output (file)
解析】指定要写入的文件。

D、io.read()

格式io.read([format])
解析】以指定格式读取 io.input() 中指定的输入文件。其中 format 格式有:

  • *l :从当前位置的 下一个位置 开始读取 整个行默认格式
  • *n :读取 下一个数字,其将作为浮点数整数
  • *a :从当前位置的 下一个位置 开始读取 整个文件
  • number :这是一个数字,表示要 读取的字符的个数

E、io.write()

格式io.write(data)
解析】将指定的数据 data 写入到 io.output()指定的输出文件

??(2)常用实例函数

A、file:read()

这里的 file 使用的是 io.open() 函数返回的 file ,其实际就是 Lua 中的一个对象。其用法与 io.read() 的相同。

B、file:write()

用法与 io.write() 的相同。

C、file:seek()

格式file:seek ([whence [, offset]])
解析】该函数用于获取或设置文件读写指针的当前位置。
位置从 1 开始计数,除文件最后一行外,每行都有行结束符,其会占两个字符位置。位置 0 表示文件第一个位置的前面位置。
当seek() 为无参时会返回读写指针的当前位置。参数 whence 的值有三种,表示将指针定位的不同位置。而 offset 则表示相对于 whence 指定位置的偏移量, offset 的默认值为 0 为正表示向后偏移,为负表示向前偏移。

  • set :表示将指针定位到文件开头处,即 0 位置处
  • cur :表示指针保持当前位置不变,默认值
  • end :表示将指针定位到文件结尾处

九、分布式锁

9.1 分布式锁的工作原理

9.2 问题引入

9.3 setnx 实现方式

9.4 为锁添加过期时间

9.5 为锁添加标识

9.6 添加 Lua 脚本

9.7 Redisson 可重入锁

9.8 Redisson 红锁

9.9 分段锁

9.10 Redisson 详解

文章来源:https://blog.csdn.net/weixin_43412762/article/details/135326562
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。