Lua的标准库能与C语言的API直接实现
- 基础函数库
- 协程库
- string库
- table库
- math库
- io库
- 操作系统库
- debug库
http://cloudwu.github.io/lua53doc/manual.html#6.4
string库
字符串处理库提供了字符串处理的通用函数,如字符串查找、子串、模式匹配等。当在Lua中对字符串作索引时,第一个字符从1开始计算,而不是C语言中的0。索引可以是负数,表示从字符串末尾反向解析。也就是说,最后一个字符在-1位置上。
字符串库中的所有函数都在表string
中,它还将其设置为字符串元表的__index
域。因此,可以以面向对象的方式使用字符串函数。
- Lua中没有字符串类型,Lua的
string
类型表示字符序列。 -
string
字符序列中字符采用8位编码,可存放任意二进制数据。 -
string
是不可变的值,修改后会返回新string
,原有string
保持不变。 -
string
字面值采用单引号或双引号包裹 -
string
使用[[
和]]
界定字符串 - Lua提供运行时数字和字符的自动转换
- 长度操作符
#
可获取字符串的长度即字符个数
原始Lua解释器操作字符串的能力有限,只能创建字符串常量、连接字符串、获取字符串长度。无法提取子串或检索字符串内容。Lua中字符串操作能力源于string
库。
基础字符串函数
-
string.len(str)
获取字符串的长度
local str = "hi lua\t, what\n lua\000"
print(string.len(str), #str) --19 19
-
string.rep(str, n)
字符串重复n次并拼接返回
local str = "-"
local result = string.rep(str,10)
print(result)-- ----------
-
string.lower(str)
字符串转小写
local str = "String.Lower"
local result = string.lower(str)
print(result) -- string.lower
local result = string.upper(str)
print(result) -- STRING.LOWER
local result = string.reverse(str)
print(result) -- rewoL.gnirtS
-
string.sub(str, begin[, end])
截取字符串
local str = "[this is a island]"
local result = string.sub(str, 2, -2)
print(str, result)
-- [this is a island]
-- this is a island
对字符串数组排序且不区分大小写
local arr = {"Alice", "Mary", "carl", "Fifi", "jay"}
table.sort(arr, function(x,y)
return string.lower(x) < string.lower(y)
end)
print(table.concat(arr,",")) --Alice,carl,Fifi,jay,Mary
-
string.char(...)
将数字编码转换为字符串
print(string.char(97, 100, 101)) --ade
-
string.byte(...)
将字符转换为数字
print(string.byte("abc", 3)) --99
print(string.byte("abcde", 3, 5)) -- 99 100 101
-
string.format(format, ...)
格式化字符串
print(string.format("pi = %.4f", math.pi)) -- pi = 3.1416
print(string.format(
"%4d-%02d-%02d %02d:%02d:%02d",
os.date("%Y"),
os.date("%m"),
os.date("%d"),
os.date("%H"),
os.date("%M"),
os.date("%S")
))
-- 2018-12-07 23:45:02
模式匹配函数
Lua中的匹配模式直接用常规的字符串来描述,用于模式匹配函数string.find
、string.match
、string.gmatch
、string.gsub
。
Lua即没有使用POSIX也没有使用Perl正则表达式来进行模式匹配,其原因主要是考虑到Lua的大小。
Lua中的模式匹配字符串,用来表示一个字符集合,可组合使用。
-
x
表示字符x
自身 -
.
点表示任何字符 -
%a
表示任何字母 -
%c
表示任何控制字符 -
%d
表示任何数字 -
%g
表示任何除空白符外的可打印字符 -
%l
表示所有小写字母 -
%p
表示所有标点符号 -
%s
表示所有空白字符 -
%u
表示所有大写字母 -
%w
表示所有字母及数字 -
%x
表示所有16进制数字符号 -
%X
X表示任意非字母或数字的字符
所有单个字母表示的类别,若将字母改为大写均表示对应的补集。如何定义字母、空格、其他字符组取决于当前的区域设置。
-
string.find(str, pattern, [, init [, plain]])
用于在一个给定的目标字符串中搜索一个模式,匹配与自己完全相同的拷贝。当匹配成功后会返回两个值:匹配到的起始索引和结尾索引,若没有匹配到则返回nil
。
参数1:str
表示给定的目标字符串
参数2:pattern
表示待匹配的字符串
参数3:init
表示从哪里开始搜索,默认值为1,可为负数。
参数4:plain
为true
表示关闭模式匹配机制,此时函数仅做直接的查找字符子串操作,但pattern
中没有字符被看作魔法字符。注意如果给定了plain
则必须填写init
。
local str = "this is a island"
local x,y = string.find(str, "is")
print(x, y) -- 3 4
在字符串中所有换行符的位置创建表
local str = "this\nis\na\nisland"
local tbl = {}
local i = 0
while true do
i = string.find(str, "\n", i+1)
if i==nil then
break
end
tbl[#tbl + 1] = i
end
print(table.concat(tbl,","))-- 5,8,10
local pair = "name = Anna"
local start,stop,key,val = string.find(pair, "(%a+)%s*=%s*(%a+)")
print(start, stop ,key, val)-- 1 11 name Anna
-
string.match(str, pattern, [, init])
在目标字符串str中找到第一个能用pattern
匹配到的部分,若找到则match
返回其中捕获的字符串,否则返回nil
。若pattern
中未指定捕获则返回整个pattern
捕获到的字符串。可选参数init
表示从哪里开始搜索默认为1可为负数。
local str = "today is 2018-12-08"
local year,month,day = string.match(str, "(%d+)-(%d+)-(%d+)")
print(year, month, day)--2018 12 08
-
string.gsub(str, pattern, replacement, [, n])
全局(global)替换子字符串
参数:
参数1:str
源字符串
参数2:pattern
匹配模式
参数3:将匹配模式pattern
匹配到的字符串替换为replacement
参数4:n
可选表示只看源字符串的前n
个字符
返回值
返回值1:替换后的字符串
返回值2:替换的次数
function trim(str)
return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
end
print(trim("\t jun chow ")); -- jun chow
math库
-- 获取圆周率
print(math.pi) -- 3.1415926535898
-- 获取Lua可表示最大数字
print(math.huge) -- inf
-- 设置随机种子,在使用math.random函数前必须先设置。
print(math.randomseed(os.time()))
-- 生成0到1之间的随机数
print(math.random()) -- 0.001251220703125
-- 生成1到100之间的随机数
print(math.random(100)) -- 57
-- 生成6位随机数
print(math.random(100000, 999999)) -- 273968
table库
Lua中table
表具有以下特性
-
table
表是一个关联数组,数组的索引可以是数字或字符串。 -
table
表默认初始索引以1开始 -
table
表的变量是一个地址引用,对table
的操作不会产生数据影响。 -
table
表可自动扩容
table
库由辅助函数构成,默认会将table
作为数组来操作。
- table.concat(table, separator, start, end)
- table.insert(table, position, value)
- table.remove(table, position)
- table.sort(table, compare)
table.insert(table, position, value)
用于将元素value
插入到数组table
的指定位置position
,会移动后续元素以腾出空间。其中位置参数position
为可选,默认为数组末尾。
local tbl = {"alpha", "beta", "gamma"}
table.insert(tbl, "delta")
table.insert(tbl, "epsilon")
table.insert(tbl, "zeta")
print(table.concat(tbl, ","))-- alpha,beta,gamma,delta,epsilon,zeta
local tbl = {1, 2, 3}
table.insert(tbl, 1, 10)
for i,v in ipairs(tbl) do
print(i,v)-- 10 1 2 3
end
table.remove(table, position)
删除并返回table
数组指定位置position
上的元素,并将该位置之后的所有元素前移,以填补空隙。如果在调用此函数时不指定位置position
参数,则会删除数组的最后一个元素。
local tbl = {"alpha", "beta", "gamma"}
table.remove(tbl)
print(table.concat(tbl, ","))-- alpha,beta
table.concat(table, separator, start, end)
table.concat
接收一个字符串数组并返回字符串连接后的结果。列出参数中指定数组table
从开始位置start
到结束位置end
的所有元素,元素间以指定分隔符separator
隔开。除了table
外,其他参数都不是必须的,分隔符separator
默认是空字符,开始位置start
默认为1,结束位置end
默认为数组的长度。
local tbl = {"alpha", "beta", "gamma"}
print(table.concat(tbl)) --alphabetagamma
print(table.concat(tbl,","))--alpha,beta,gamma
print(table.concat(tbl, 2, 3))-- gamma
扩展table.concat
使其能处理嵌套的字符串数组
function concat(tbl)
if type(tbl)~="table" then
return tbl
end
local result = {}
for i=1,#tbl do
result[i] = concat(tbl[i])
end
return table.concat(result)
end
-- test
local arr = {
{"a", {" nice "}},
"and",
{{" long "}, "list"}
}
print(concat(arr))--a nice and long list
table.sort(table, compare)
table.sort()
函数对给定的table
进行升序排序,其中compare
为可选参数,可以是一个外部函数用来自定义排序标准。排序函数的标准是接收两个参数并返回一个布尔型的值,若布尔值为true
则表示升序否则则为降序。
在table
中索引是一个无序的集合,若要对其进行排序则必 须将其复制到一个数组中,然后对数组元素进行排序。值得注意的,对于Lua而言,数组也是无序的,它们的本质都是table
。
-- 对键名进行排序的迭代器
function pairsByKeys(tbl, fn)
-- 获取键名
local result = {}
for k,v in pairs(tbl) do
result[#result + 1] = k
end
-- 对键名进行排序
table.sort(result, fn)
-- 迭代器
local i = 0 --迭代器变量
return function()
i = i + 1
return result[i], tbl[result[i]]
end
end
-- test
local fns = {
set=10,
get=100,
count=29
}
for index,value in pairsByKeys(fns) do
print(index, value)
end
--[[
count 29
get 100
set 10
--]]
操作系统库
Lua操作系统库函数,包含了文件管理、系统时钟等于操作系统相关信息,这些函数定义在表os
中。
日期时间
- os.clock() 返回程序使用CPU时间的近似值
- os.time([table]) 默认获取当前时间戳,可指定日期时间的
table
参数。 - os.date([format [, time]]) 格式化时间戳为可读时间,
time
为可选默认省略时为当前时间戳。 - os.difftime(ts2, ts1) 返回时间戳ts1到时间戳ts2相差的秒数
os.clock()
-
os.clock()
返回程序使用CPU时间的近似值
print(os.clock(), string.format("%.2f", os.clock())) -- 0.0 0.00
计算程序执行消耗的CPU秒数
local clock_begin = os.clock()
local sum = 0
for i=1, 1000000 do
sum = sum + i
end
local clock_end = os.clock()
print(string.format("elapsed seconds is %.2f\n", clock_end - clock_begin))
-- elapsed seconds is 0.02
-
os.clock()
的实现是调用C语言的函数库,其中CLOCKS_PER_SEC
值在不同平台有着不同定义。
static int os_clock(lua_State *L){
lua_pushnumber(L, (lua_Number))/(lua_Number)CLOCKS_PER_SEC;
return 1;
}
- 可使用
socket
库的socket.gettime()
替代os.clock()
require "socket"
local time = socket.gettime()
- 要注意函数的溢出问题,程序运行时间太长的话,使用
clock
有可能返回负数。
os.time([table])
按table
内容返回一个数字时间值,若无参数则返回当前时间table
的字段。返回一个指定时间点的UNIX时间戳,若无参数调用则返回当前时间点的UNIX时间戳。
-- 获取当前UNIX的10位秒级时间戳
print(os.time()) -- 1544030239
-- 获取指定日期时间的时间戳
os.time({year=2018, month=06, day=05, hour=12, min=23, sec=45, isdst=true})
os.date([format [, time]])
os.date
是os.time
的反函数,将一个UNIX时间戳装换成可读的字符串形式。若省略第二个参数time
则默认返回当前时间点的日期。返回按format
格式化后的日期、时间的字符串或表。若设置time
参数,则按time
指定的时间格式进行格式化,否则按当前时间格式化。
print(os.date()) -- 12/06/18 01:21:35
print(os.date("%Y-%m-%d %H:%M:%S")) -- 2018-12-06 01:22:06
参数说明:
format
参数为空则按当前系统的设置返回格式化后的字符串,为了生成日期的table
可使用格式字符串*t
。
-
!
按格林威治时间进行格式化 -
*t
返回带4位年、1-12的月份,1-31的日期、0-23的小时数、0-59分钟数、 0-61秒数、1-7星期数
local tbl = os.date("*t", os.time())
for k,v in pairs(tbl) do
print(k, v)
end
--[[
yday 340
year 2018
sec 21
day 6
month 12
hour 1
min 25
isdst false
wday 5
--]]
os.date
会将日期格式化为一个字符串,此字符串是传入格式字符串的副本,其中某些特殊表被替换成时间和日期信息,所有标记都以%
开头,并伴随一个字符。
%a 一个星期中天数的简写
%A 一个星期找那个天数的全称
%b 月份简写
%B 月份全称
%c 日期和时间
%d 一个月中的第几天
%H 24小时制中的小时数
% I 12小时制中的小时数
%j 一年中的第几天
%M 分钟数
%m 月份数
%P 上午am或下午pm
%S 秒数
%w 一星期中的第几天
%W 一年中第几个星期
%x 日期
%X 时间
%y 两位数的年份
%Y 完整的年份
%% 字符串%
时间戳转为日期
function ts2date(ts)
local tbl = {}
local date = string.format(os.date("%x", ts))
local arr = string.split(date, "/")
tbl.YEAR = checkint(arr[3])
tbl.MONTH = checkint(arr[1])
tbl.DAY = checkint(arr[2])
return tbl
end
计算时间戳间隔天数
function diff_days(mints, maxts)
local temp = nil
if maxts<mints then
temp = mints
mints = maxts
maxts = temp
end
return checkint(maxts/86400) - checkint(mints/86400)
end
os.difftime(t2, t1)
返回时间戳ts1到ts2相差的秒数,可用于计算代码的执行时长。
local ts1 = os.time()
for i=0,10000000 do
math.random()
end
local ts2 = os.time()
print(os.difftime(ts2, ts1)) --1.0
系统调用
os.execute([command])
系统级的函数调用os.execute
相当于·C语言中的system()
,函数有缺省的参数command
,函数是解析command
后在通过系统来调用解析的结果,返回一个依赖于操作系统的状态码。当参数缺省时,若操作系统可以调用解析参数则返回非0的数否则返回0。
local ret = os.execute()
if ret ~= 0 then
os.execute("color 02") -- 将命令行的颜色由白色修改为绿色
os.execute("copy test.lua test.lua.bak")
os.execute("pause")
end
os.exit(code)
按任意键继续...,相当于C语言中的exit
函数,终止主程序,code
为返回值。
-- 结束程序并返回状态码,0代表成功。
print("run then exit")
os.exit(0)
print("can't output")
-- run then exit
os.setlocale(locale[, category])
设置程序本地配置,函数返回最新配置,若失败则返回nil
。
os.setlocale("zh_CN.utf8", "time")
print(os.date())
local
指定当前配置名称的字符串
- "" 空字符串表示当前配置被视为本地配置
- "c" 表示当前配置被视为标准C配置
- nil 返回category设置的配置名称的当前值
category
描述待更改的配置名称
- all
- collate
- ctype
- monetary
- numeric
- time
os.getenv(varname)
返回当前进程的环境变量varname
(不区分大小写)的值,若变量没有定义时返回为nil
。
-- 获取操作系统名称
print(os.getenv("OS")) -- Windows_NT
-- 获取系统用户名
print(os.getenv("USERNAME")) -- jc
-- 获取当前登录服务器名称
print(os.getenv("LOGONSERVER")) -- \\WIN10-JC
-- 获取用户域名
print(os.getenv("USERDOMAIN")) -- WIN10-JC
-- 获取计算机名称
print(os.getenv("COMPUTERNAME")) -- WIN10-JC
-- 获取处理器cpu数量
print(os.getenv("NUMBER_OF_PROCESSORS")) -- 8
-- 获取处理器CPU修订号
print(os.getenv("PROCESSOR_REVISION")) -- 3c03
-- 获取处理器CPU的型号
print(os.getenv("PROCESSOR_LEVEL")) -- 6
-- 获取处理器CPU的架构
print(os.getenv("PROCESSOR_ARCHITECTURE")) -- AMD64
-- 获取处理器CPU标识
print(os.getenv("PROCESSOR_IDENTIFIER")) -- Intel64 Family 6 Model 60 Stepping 3, GenuineIntel
-- 获取命令行解释器可执行程序的完整路径
print(os.getenv("COMSPEC")) -- C:\WINDOWS\system32\cmd.exe
print(os.getenv("ComSpec")) -- C:\WINDOWS\system32\cmd.exe
-- 获取系统支持的文件扩展名
print(os.getenv("PATHEXT")) -- .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
-- 获取用户主目录的本地驱动器(本地盘符)
print(os.getenv("HOMEDRIVE")) -- C:
-- 获取系统根目录
print(os.getenv("SystemRoot")) -- C:\WINDOWS
-- 获取用户配置文件路径
print(os.getenv("ALLUSERSPROFILE")) -- C:\ProgramData
-- 获取用户主目录完整路径
print(os.getenv("HOMEPATH")) -- \Users\jc
-- 获取系统临时目录完整路径
print(os.getenv("TEMP")) -- C:\Users\jc\AppData\Local\Temp
print(os.getenv("ProgramFiles")) -- C:\Program Files
print(os.getenv("APPDATA")) -- C:\Users\jc\AppData\Roaming
print(os.getenv("CommonProgramFiles")) -- C:\Program Files\Common Files
os.tmpname()
返回临时文件名称,自动产生临时文件并返回文件名如/tmp/sc9k
,如果要使用,必须手动打开文件,最后不使用时必须手动删除。io.tmpfile()
产生的临时文件程序结束后会自动删除。
print(os.tmpname()) --\sc9k.
os.rename(oldname, newname)
更改文件或目录名,若函数调用失败则返回nil
和错误信息。
os.remove(filename)
删除文件或空白目录,若函数调用失败则返回nil
和错误信息。
io库
Lua I/O库用于读取和处理文件,提供两套不同风格的文件处理接口(模型),分为简单模式(和C语言一样)和完全模式。
- 简单模式(simple model)
使用隐式的文件句柄,假设有一个当前当前输入文件和一个当前输出文件,提供默认输入文件和输出文件的操作。拥有一个当前输入文件和一个当前输出文件,提供针对这些文件相关的操作。
使用隐含的文件描述符,有操作设置默认的输入文件和输出文件。
- 完全模式(complete model)
使用显式文件句柄,使用外部的文件句柄来实现,以面向对象的方式,将所有文件操作定义为文件句柄的方法。
明确的操作描述符
使用明确的文件描述符时,所有操作由表io
提供,使之能够在同一时间内处理多个文件,功能相当相似的隐式文件操作符。
-- 使用明确的文件描述符能够在同一时间处理多个文件
file:function
-- eg
file = io.open("test.lua", "r")
print(file:read())
file:close()
file = io.open("test.lua", "a")
file:write("---------------------")
file:close()
io.open
返回文件操作符和操作方法,表io
提供3个与定义的文件描述符:
io.stderr 标准错误输出
io.stdin 标准输入
io.stdout 标准输出
io
表调用方式
表io中提供三个和C语言中含义相同的预定义文件句柄:io.stdin
、io.stdout
、io.stderr
。IO库永远不会关闭这些文件。
使用io
表,io.open()
将返回指定文件的描述,且所有的操作将围绕这个文件描述io表同样提供3中预定义的文件描述:io.stdin
、io.stdout
、io.stderr
。
- 文件句柄直接调用方式
使用file:xxx()
函数方式进行操作,其中file
为ioi.open()
返回的文件句柄,多数io
函数调用失败时返回nil
和错误信息。
除非另有说明,IO函数在出错时都返回nil
,第二个返回值为错误消息,第三个返回值为系统相关的错误代码。成功时返回与nil
不同的值。
简单模式
简单模式的所有操作都作用于两个当前文件,I/O库将当前输入文件初始化为进程标准输入stdin
,将当前输出文件初始化为进程标准输出stdout
。
I/O库会将标准输入输出作为其缺省的输入文件和输出文件,可通过io.input(filename)
和io.output(filename)
来改变当前输入输出文件。
使用io.write()
和io.read()
从标准输入stdin
读取输出到标准输出stdout
,在执行io.read()
操作时,会从标准输入中读取一行。使用io.input()
和io.output()
改变当前文件。
io.input(filename)
以只读模式打开指定文件,并将其设定为当前输入文件,除非再次调用io.input()
,否则所有的输入都将来源于这个文件。
io.input([file])
相当于io.input
,但操作在默认输出文件上。使用文件名调用时,以文本模式来打开该名称的文件,并将文件句柄设置为默认输入文件。若使用文件句柄去调用它,则简单地将句柄设置为默认输入文件。若调用时不传入参数则返回当前的默认输出文件。在出错的情况下,函数抛出错误而非返回错误码。
io.output(filename)
在输出方面,io.output()
也可以完成类似的工作。
io.output([file])
使用文件名称调用时,以文本模式打开该名称的文件,并将文件句柄设置为默认输出文件。若使用文件句柄去调用它,就简单地将该句柄设置为默认输出和文件。若调用时不传入参数则返回当前的默认输出文件。
io.read()
io.read(...)
# 相当于
io.input():read
按指定的格式读取一个文件,按每个格式函数将返回一个字符串或数字,若不能正确地读取将返回nil
,若没有指定格式将指默认按行方式进行读取。
读取格式
-
*a
从当前位置读取整个文件,若为文件结尾EOF
则返回空字符串。
io.read("*all")
读取当前输入文件的所有内容,以当前位置作为开始。若当前位置处于文件末尾或文件为空则返回空字符串。由于Lua可以高效地处理长字符串,因此在Lua中可先将数据从文件中完整读出之后在通过字符串库提供的函数进行各种处理。
-
*l
默认选项,读取下一行的内容,若为文件结尾EOF
则返回nil
。
io.read("*line")
-- eg
for count = 1, math.huge do
local line = io.read("*line") -- 缺省值为 *line
if line == nil then
break
end
io.write(string.format("%6d", count), line, "\n")
end
-- 若为了迭代文件中所有行可使用 io.lines ,以迭代器的形式访问文件中的每一行数据。
local lines = {}
-- 通过迭代器访问每行数据
for line in io.lines() do
lines[#lines+1] = line
end
-- 使用Lua标准库table进行排序
table.sort(lines)
for _,l in ipairs(lines) do
io.write(l, "\n")
end
返回当前文件的下一行但不包含换行符,当到达文件末尾时则返回nil
。
-
number
读取指定字节数的字符,若为文件结尾EOF
则返回nil
,若number为0则返回空字符串。
io.read("*number")
-- eg:读取注释中的数字
while true do
local n1,n2,n3 = io.read("*number", "*number", "*number")
if not n1 then
break
end
print(math.max(n1,n2,n3))
end
从当前输入文件中读取一个数字,此时read
将直接返回一个数字而非字符串。*number
选项会忽略数字前面所有的空格,且能处理像-3
、+5.2
这样的数字格式。若当前读取的数据不合法则返回nil
。调用时可指定多个选项,函数会根据每个选项参数返回相应的内容。
-
*n
读取一个数字并返回它
-- 从输入文件中最多读取n个字符,若读取不到任何字符则返回 nil,否则返回读取到的字符串。
io.read(<num>)
-- eg
while true do
local block = io.read(2^13)
if not block then
break
end
io.write(block)
end
-- 特殊情况,用于检查是否到达文件末尾,若尚未到达则返回空字符串否则返回 nil。
io.read(0)
io.write(...)
-- 将所有参数顺序的写入到当前输出文件中
io.write(...)
-- 相当于
io.output():write
-- eg:获取任意数目的字符串参数并将其写入当前标准输出中
local t = io.write("sin(3)=", math.sin(3), "\n")
print("hello", "lua")
io.write
与print
不同之处在于,io.write
不附加任何额外的字符到输出中,例如制表符、换行符等。io.write
是使用当前输出文件而print
始终使用标准输出。print
会自动调用参数的tostring
方法,所以可以显示出表、函数和nil
。
io.open(filename [,mode])
按指定模式mode
打开一个文件,成功则返回新的文件句柄,失败则返回nil
和错误信息。
文件模式
- r 默认选项,只读模式,对已存在的文件的默认打开模式。
- w 可写模式,允许修改已存在的文件和创建新文件且不可读取。
- a 追加模式,对于已存在的文件允许追加新内容,但不允许修改原来内容,同时也可以创建新文件。
- r+ 更新模式,之前数据将被保存。读写模式,打开已存在的文件。
- w+ 更新模式,之前数据将被清除。若文件已存在则删除文件中的数据,若文件不存在则创建文件,并以读写模式打开。
- a+ 添加更新模式,之前数据将被保存,仅允许在文件末尾进行添加。以可读的追加模式打开已存在的文件,若文件不存在则新建文件。
- b 某些系统支持二进制方式
-- 读取指定文件
function getFile(filename)
local file = assert(io.open(filename, "r"))
local string = file:read("*all")
file:close()
return string
end
-- 按行方式读取文件内容
function getFileLine(filename)
local BUFSIZE = 84012
local file = assert(io.open(filename, "r"))
local lines,rest = file:read(BUFSIZE, "*line")
file:close()
return lines,rest
end
-- 以字符串方式写入文件
function writeFile(filename, string)
local file = assert(io.open(filename, "w"))
file:write(string)
file:close()
end
-- 控制台写入字符串到文件
function writeConoleToFile(filename)
local file = assert(io.open(filename, "w"))
local string = io.read()
file:write(string)
file:close()
ene
io.popen([prog[, mode]])
开始程序prog
与额外的进程,并返回用于prog
的文件句柄,并不支持所有的系统平台。
使用一个分离进程开启程序program
,返回的文件句柄可用于从这个程序中读取数据(mode=r
)或是向程序写入输入(mode=w
)。
io.close(file)
io.close([file])
# 相当于
file:close()
关闭默认的输出文件,当文件句柄被垃圾收集后,文件将自动关闭,句柄将变为一个不可预知的值。
io.tmpfile()
返回一个临时文件句柄,该文件以更新模式打开,程序结束时自动删除。
io.type(obj)
检测obj
是否为一个可用的文件句柄,若obj
是一个打开的文件句柄则返回字符串file
,若obj
是一个关闭的文件句柄则返回字符串close file
。若obj
不是句柄则返回nil
。
返回值
-
file
为一个打开的文件句柄 -
close file
为一个已关闭的文件句柄 -
nil
表示obj
不是一个文件句柄
io.flush()
io.flush()
# 相当于
file:flush()
向文件写入缓冲中的所有数据,输出所有缓冲区中的内容到默认输出文件。
io.lines(optional filename)
io.lines([filename])
提供一个循环迭代器以遍历文件,若指定文件名则当遍历结束后将自动关闭该文件,若使用默认文件则遍历结束后不会自动关闭文件。
打开指定的文件filename
为读模式并返回一个迭代函数,每次调用将获取文件中的一行内容,当到达文件结尾时,将返回nil
并自动关闭文件。
若不带参数时,io.lines()
相当于io.input():lines()
,表示读取默认输入设备的内容但结束时不关闭文件。
返回一个迭代函数,每次调用将获得文件中的一行内容,当到达文件结尾时将返回nil,但不关闭文件。
for line in io.lines("main.lua") do
print(line)
end
debug库
Lua本身并未内置调试器,提供了debug
库用于提供创建自定义调试器的功能。出于性能考虑,调用基本功能的正式接口都是通过 C API提供,在Lua中访问debug
库的一种方式是通过Lua代码直接访问。与其他库不同的debug
库很多功能都会影响性能。其次,它打破了Lua中一些颠覆不破的真理,如在一个局部变量的作用域之外不能访问。
debug
库中的一种重要的思想是栈级别(stack level),一个栈级别就是一个指向在当前时刻正在活动的特殊函数的数字。也就是说,这个函数正在被调用但还没有返回。调用debug
库的函数级别为1,调用它的函数级别为2,以此类推。
Lua的调试库包含两种函数:自省函数(introspective functions)和钩子(hooks)。自省函数可用来监视一个正在运行的程序的信息,如活动函数的栈、当前的执行行、局部变量值和名称等。钩子可以跟踪程序的运行。自省函数主要是debug.getinfo
。
自省函数
- debug.getinfo([thread,]func[,what]) 返回一个函数的信息表
- debug.traceback([thread,][message[, level]]) 获取调用栈的回溯信息
debug.getinfo([thread,]func[,what])
debug.getinfo
参数
-
func
可直接传入函数,也可传入一个数值,此数值表示函数(运行在指定线程)的调用栈深度,0表示getinfo
自己,1表示调用getinfo
的函数,以此类推一般是2。若此数值大于活动函数的深度返回nil
。 -
what
函数类型,若func
是一个普通的Lua函数则为Lua
,若func
是一个C函数则为C
,若是Lua主程序块(chunk)部分则为main
。
debug.getinfo
返回值是一个table
包含以下字段
-
source
函数定义的位置,若函数时通过loadstring
在一个字符串中定义的,那么source
就是这个字符串。若函数是在一个文件中定义的,那么source
就是这个文件名加前缀@
。 -
short_src
是source
的短版本,最多60个字符,可用于错误信息汇总。 -
linedefined
该函数定义的源代码中第一行的行号
-- 获取当前栈的追溯信息
function traceback()
-- 获取相应栈层上函数的信息
for level=1,math.huge do
-- 获取函数信息
-- S 选择
-- source 函数定义的位置
-- short_src 函数定义位置的短版本,最多60个字符。
-- what 函数的类型
-- linedefined 函数定义在源代码中第一行的行号
-- lastlinedefined 函数定义在源代码中最后一行的行号
-- l 选择
-- currentline 当前所在行
local info = debug.getinfo(level, "Sl")
-- 判断是否具有上层函数
if not info then
break
end
-- 判断是否为一个C函数
if info.what=="C" then
print(level, "C function")
else
print(string.format("file:%s line:%d", info.short_src, info.currentline))
end
end
end
traceback()
--[[
file:D:\lua\test\test.lua line:6
file:D:\lua\test\test.lua line:19
3 C function
--]]
debug.traceback([thread,][message[, level]])
获取调用栈的回溯信息
debug.traceback
参数
-
message
字符串 可选项 被添加在栈回溯信息的开头。 -
level
数值 可选项 指明从栈的哪一层开始回溯,默认为1即调用traceback
的位置。
若有message
值且不是字符串或nil
,traceback
函数不做任何处理直接返回message
,否则返回调用栈的回溯信息。
自定义的调试器
function __G__TRACKBACK__(errmsg)
print("LUA ERROR: "..tostring(errmsg).."\n")
print(debug.traceback("", 2))
end