Lua的標(biāo)準(zhǔn)庫(kù)能與C語(yǔ)言的API直接實(shí)現(xiàn)
- 基礎(chǔ)函數(shù)庫(kù)
- 協(xié)程庫(kù)
- string庫(kù)
- table庫(kù)
- math庫(kù)
- io庫(kù)
- 操作系統(tǒng)庫(kù)
- debug庫(kù)
http://cloudwu.github.io/lua53doc/manual.html#6.4
string庫(kù)
字符串處理庫(kù)提供了字符串處理的通用函數(shù),如字符串查找、子串、模式匹配等。當(dāng)在Lua中對(duì)字符串作索引時(shí),第一個(gè)字符從1開(kāi)始計(jì)算,而不是C語(yǔ)言中的0。索引可以是負(fù)數(shù),表示從字符串末尾反向解析。也就是說(shuō),最后一個(gè)字符在-1位置上。
字符串庫(kù)中的所有函數(shù)都在表string中,它還將其設(shè)置為字符串元表的__index域。因此,可以以面向?qū)ο蟮姆绞绞褂米址瘮?shù)。
- Lua中沒(méi)有字符串類型,Lua的
string類型表示字符序列。 -
string字符序列中字符采用8位編碼,可存放任意二進(jìn)制數(shù)據(jù)。 -
string是不可變的值,修改后會(huì)返回新string,原有string保持不變。 -
string字面值采用單引號(hào)或雙引號(hào)包裹 -
string使用[[和]]界定字符串 - Lua提供運(yùn)行時(shí)數(shù)字和字符的自動(dòng)轉(zhuǎn)換
- 長(zhǎng)度操作符
#可獲取字符串的長(zhǎng)度即字符個(gè)數(shù)
原始Lua解釋器操作字符串的能力有限,只能創(chuàng)建字符串常量、連接字符串、獲取字符串長(zhǎng)度。無(wú)法提取子串或檢索字符串內(nèi)容。Lua中字符串操作能力源于string庫(kù)。
基礎(chǔ)字符串函數(shù)
-
string.len(str)獲取字符串的長(zhǎng)度
local str = "hi lua\t, what\n lua\000"
print(string.len(str), #str) --19 19
-
string.rep(str, n)字符串重復(fù)n次并拼接返回
local str = "-"
local result = string.rep(str,10)
print(result)-- ----------
-
string.lower(str)字符串轉(zhuǎn)小寫(xiě)
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
對(duì)字符串?dāng)?shù)組排序且不區(qū)分大小寫(xiě)
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(...)將數(shù)字編碼轉(zhuǎn)換為字符串
print(string.char(97, 100, 101)) --ade
-
string.byte(...)將字符轉(zhuǎn)換為數(shù)字
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
模式匹配函數(shù)
Lua中的匹配模式直接用常規(guī)的字符串來(lái)描述,用于模式匹配函數(shù)string.find、string.match、string.gmatch、string.gsub。
Lua即沒(méi)有使用POSIX也沒(méi)有使用Perl正則表達(dá)式來(lái)進(jìn)行模式匹配,其原因主要是考慮到Lua的大小。
Lua中的模式匹配字符串,用來(lái)表示一個(gè)字符集合,可組合使用。
-
x表示字符x自身 -
.點(diǎn)表示任何字符 -
%a表示任何字母 -
%c表示任何控制字符 -
%d表示任何數(shù)字 -
%g表示任何除空白符外的可打印字符 -
%l表示所有小寫(xiě)字母 -
%p表示所有標(biāo)點(diǎn)符號(hào) -
%s表示所有空白字符 -
%u表示所有大寫(xiě)字母 -
%w表示所有字母及數(shù)字 -
%x表示所有16進(jìn)制數(shù)字符號(hào) -
%XX表示任意非字母或數(shù)字的字符
所有單個(gè)字母表示的類別,若將字母改為大寫(xiě)均表示對(duì)應(yīng)的補(bǔ)集。如何定義字母、空格、其他字符組取決于當(dāng)前的區(qū)域設(shè)置。
-
string.find(str, pattern, [, init [, plain]])用于在一個(gè)給定的目標(biāo)字符串中搜索一個(gè)模式,匹配與自己完全相同的拷貝。當(dāng)匹配成功后會(huì)返回兩個(gè)值:匹配到的起始索引和結(jié)尾索引,若沒(méi)有匹配到則返回nil。
參數(shù)1:str表示給定的目標(biāo)字符串
參數(shù)2:pattern表示待匹配的字符串
參數(shù)3:init表示從哪里開(kāi)始搜索,默認(rèn)值為1,可為負(fù)數(shù)。
參數(shù)4:plain為true表示關(guān)閉模式匹配機(jī)制,此時(shí)函數(shù)僅做直接的查找字符子串操作,但pattern中沒(méi)有字符被看作魔法字符。注意如果給定了plain則必須填寫(xiě)init。
local str = "this is a island"
local x,y = string.find(str, "is")
print(x, y) -- 3 4
在字符串中所有換行符的位置創(chuàng)建表
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])在目標(biāo)字符串str中找到第一個(gè)能用pattern匹配到的部分,若找到則match返回其中捕獲的字符串,否則返回nil。若pattern中未指定捕獲則返回整個(gè)pattern捕獲到的字符串。可選參數(shù)init表示從哪里開(kāi)始搜索默認(rèn)為1可為負(fù)數(shù)。
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)替換子字符串
參數(shù):
參數(shù)1:str 源字符串
參數(shù)2:pattern 匹配模式
參數(shù)3:將匹配模式pattern匹配到的字符串替換為replacement
參數(shù)4:n可選表示只看源字符串的前n個(gè)字符
返回值
返回值1:替換后的字符串
返回值2:替換的次數(shù)
function trim(str)
return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
end
print(trim("\t jun chow ")); -- jun chow
math庫(kù)

-- 獲取圓周率
print(math.pi) -- 3.1415926535898
-- 獲取Lua可表示最大數(shù)字
print(math.huge) -- inf
-- 設(shè)置隨機(jī)種子,在使用math.random函數(shù)前必須先設(shè)置。
print(math.randomseed(os.time()))
-- 生成0到1之間的隨機(jī)數(shù)
print(math.random()) -- 0.001251220703125
-- 生成1到100之間的隨機(jī)數(shù)
print(math.random(100)) -- 57
-- 生成6位隨機(jī)數(shù)
print(math.random(100000, 999999)) -- 273968
table庫(kù)
Lua中table表具有以下特性
-
table表是一個(gè)關(guān)聯(lián)數(shù)組,數(shù)組的索引可以是數(shù)字或字符串。 -
table表默認(rèn)初始索引以1開(kāi)始 -
table表的變量是一個(gè)地址引用,對(duì)table的操作不會(huì)產(chǎn)生數(shù)據(jù)影響。 -
table表可自動(dòng)擴(kuò)容
table庫(kù)由輔助函數(shù)構(gòu)成,默認(rèn)會(huì)將table作為數(shù)組來(lái)操作。

- 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插入到數(shù)組table的指定位置position,會(huì)移動(dòng)后續(xù)元素以騰出空間。其中位置參數(shù)position為可選,默認(rèn)為數(shù)組末尾。
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數(shù)組指定位置position上的元素,并將該位置之后的所有元素前移,以填補(bǔ)空隙。如果在調(diào)用此函數(shù)時(shí)不指定位置position參數(shù),則會(huì)刪除數(shù)組的最后一個(gè)元素。
local tbl = {"alpha", "beta", "gamma"}
table.remove(tbl)
print(table.concat(tbl, ","))-- alpha,beta
table.concat(table, separator, start, end)
table.concat接收一個(gè)字符串?dāng)?shù)組并返回字符串連接后的結(jié)果。列出參數(shù)中指定數(shù)組table從開(kāi)始位置start到結(jié)束位置end的所有元素,元素間以指定分隔符separator隔開(kāi)。除了table外,其他參數(shù)都不是必須的,分隔符separator默認(rèn)是空字符,開(kāi)始位置start默認(rèn)為1,結(jié)束位置end默認(rèn)為數(shù)組的長(zhǎng)度。
local tbl = {"alpha", "beta", "gamma"}
print(table.concat(tbl)) --alphabetagamma
print(table.concat(tbl,","))--alpha,beta,gamma
print(table.concat(tbl, 2, 3))-- gamma
擴(kuò)展table.concat使其能處理嵌套的字符串?dāng)?shù)組
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()函數(shù)對(duì)給定的table進(jìn)行升序排序,其中compare為可選參數(shù),可以是一個(gè)外部函數(shù)用來(lái)自定義排序標(biāo)準(zhǔn)。排序函數(shù)的標(biāo)準(zhǔn)是接收兩個(gè)參數(shù)并返回一個(gè)布爾型的值,若布爾值為true則表示升序否則則為降序。
在table中索引是一個(gè)無(wú)序的集合,若要對(duì)其進(jìn)行排序則必 須將其復(fù)制到一個(gè)數(shù)組中,然后對(duì)數(shù)組元素進(jìn)行排序。值得注意的,對(duì)于Lua而言,數(shù)組也是無(wú)序的,它們的本質(zhì)都是table。
-- 對(duì)鍵名進(jìn)行排序的迭代器
function pairsByKeys(tbl, fn)
-- 獲取鍵名
local result = {}
for k,v in pairs(tbl) do
result[#result + 1] = k
end
-- 對(duì)鍵名進(jìn)行排序
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
--]]
操作系統(tǒng)庫(kù)
Lua操作系統(tǒng)庫(kù)函數(shù),包含了文件管理、系統(tǒng)時(shí)鐘等于操作系統(tǒng)相關(guān)信息,這些函數(shù)定義在表os中。

日期時(shí)間
- os.clock() 返回程序使用CPU時(shí)間的近似值
- os.time([table]) 默認(rèn)獲取當(dāng)前時(shí)間戳,可指定日期時(shí)間的
table參數(shù)。 - os.date([format [, time]]) 格式化時(shí)間戳為可讀時(shí)間,
time為可選默認(rèn)省略時(shí)為當(dāng)前時(shí)間戳。 - os.difftime(ts2, ts1) 返回時(shí)間戳ts1到時(shí)間戳ts2相差的秒數(shù)
os.clock()
-
os.clock()返回程序使用CPU時(shí)間的近似值
print(os.clock(), string.format("%.2f", os.clock())) -- 0.0 0.00
計(jì)算程序執(zhí)行消耗的CPU秒數(shù)
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()的實(shí)現(xiàn)是調(diào)用C語(yǔ)言的函數(shù)庫(kù),其中CLOCKS_PER_SEC值在不同平臺(tái)有著不同定義。
static int os_clock(lua_State *L){
lua_pushnumber(L, (lua_Number))/(lua_Number)CLOCKS_PER_SEC;
return 1;
}
- 可使用
socket庫(kù)的socket.gettime()替代os.clock()
require "socket"
local time = socket.gettime()
- 要注意函數(shù)的溢出問(wèn)題,程序運(yùn)行時(shí)間太長(zhǎng)的話,使用
clock有可能返回負(fù)數(shù)。
os.time([table])
按table內(nèi)容返回一個(gè)數(shù)字時(shí)間值,若無(wú)參數(shù)則返回當(dāng)前時(shí)間table的字段。返回一個(gè)指定時(shí)間點(diǎn)的UNIX時(shí)間戳,若無(wú)參數(shù)調(diào)用則返回當(dāng)前時(shí)間點(diǎn)的UNIX時(shí)間戳。
-- 獲取當(dāng)前UNIX的10位秒級(jí)時(shí)間戳
print(os.time()) -- 1544030239
-- 獲取指定日期時(shí)間的時(shí)間戳
os.time({year=2018, month=06, day=05, hour=12, min=23, sec=45, isdst=true})
os.date([format [, time]])
os.date是os.time的反函數(shù),將一個(gè)UNIX時(shí)間戳裝換成可讀的字符串形式。若省略第二個(gè)參數(shù)time則默認(rèn)返回當(dāng)前時(shí)間點(diǎn)的日期。返回按format格式化后的日期、時(shí)間的字符串或表。若設(shè)置time參數(shù),則按time指定的時(shí)間格式進(jìn)行格式化,否則按當(dāng)前時(shí)間格式化。
print(os.date()) -- 12/06/18 01:21:35
print(os.date("%Y-%m-%d %H:%M:%S")) -- 2018-12-06 01:22:06
參數(shù)說(shuō)明:
format 參數(shù)為空則按當(dāng)前系統(tǒng)的設(shè)置返回格式化后的字符串,為了生成日期的table可使用格式字符串*t。
-
!按格林威治時(shí)間進(jìn)行格式化 -
*t返回帶4位年、1-12的月份,1-31的日期、0-23的小時(shí)數(shù)、0-59分鐘數(shù)、 0-61秒數(shù)、1-7星期數(shù)
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會(huì)將日期格式化為一個(gè)字符串,此字符串是傳入格式字符串的副本,其中某些特殊表被替換成時(shí)間和日期信息,所有標(biāo)記都以%開(kāi)頭,并伴隨一個(gè)字符。
%a 一個(gè)星期中天數(shù)的簡(jiǎn)寫(xiě)
%A 一個(gè)星期找那個(gè)天數(shù)的全稱
%b 月份簡(jiǎn)寫(xiě)
%B 月份全稱
%c 日期和時(shí)間
%d 一個(gè)月中的第幾天
%H 24小時(shí)制中的小時(shí)數(shù)
% I 12小時(shí)制中的小時(shí)數(shù)
%j 一年中的第幾天
%M 分鐘數(shù)
%m 月份數(shù)
%P 上午am或下午pm
%S 秒數(shù)
%w 一星期中的第幾天
%W 一年中第幾個(gè)星期
%x 日期
%X 時(shí)間
%y 兩位數(shù)的年份
%Y 完整的年份
%% 字符串%
時(shí)間戳轉(zhuǎn)為日期
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
計(jì)算時(shí)間戳間隔天數(shù)
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)
返回時(shí)間戳ts1到ts2相差的秒數(shù),可用于計(jì)算代碼的執(zhí)行時(shí)長(zhǎng)。
local ts1 = os.time()
for i=0,10000000 do
math.random()
end
local ts2 = os.time()
print(os.difftime(ts2, ts1)) --1.0
系統(tǒng)調(diào)用
os.execute([command])
系統(tǒng)級(jí)的函數(shù)調(diào)用os.execute相當(dāng)于·C語(yǔ)言中的system(),函數(shù)有缺省的參數(shù)command,函數(shù)是解析command后在通過(guò)系統(tǒng)來(lái)調(diào)用解析的結(jié)果,返回一個(gè)依賴于操作系統(tǒng)的狀態(tài)碼。當(dāng)參數(shù)缺省時(shí),若操作系統(tǒng)可以調(diào)用解析參數(shù)則返回非0的數(shù)否則返回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)
按任意鍵繼續(xù)...,相當(dāng)于C語(yǔ)言中的exit函數(shù),終止主程序,code為返回值。
-- 結(jié)束程序并返回狀態(tài)碼,0代表成功。
print("run then exit")
os.exit(0)
print("can't output")
-- run then exit
os.setlocale(locale[, category])
設(shè)置程序本地配置,函數(shù)返回最新配置,若失敗則返回nil。
os.setlocale("zh_CN.utf8", "time")
print(os.date())
local 指定當(dāng)前配置名稱的字符串
- "" 空字符串表示當(dāng)前配置被視為本地配置
- "c" 表示當(dāng)前配置被視為標(biāo)準(zhǔn)C配置
- nil 返回category設(shè)置的配置名稱的當(dāng)前值
category 描述待更改的配置名稱
- all
- collate
- ctype
- monetary
- numeric
- time
os.getenv(varname)
返回當(dāng)前進(jìn)程的環(huán)境變量varname(不區(qū)分大小寫(xiě))的值,若變量沒(méi)有定義時(shí)返回為nil。
-- 獲取操作系統(tǒng)名稱
print(os.getenv("OS")) -- Windows_NT
-- 獲取系統(tǒng)用戶名
print(os.getenv("USERNAME")) -- jc
-- 獲取當(dāng)前登錄服務(wù)器名稱
print(os.getenv("LOGONSERVER")) -- \\WIN10-JC
-- 獲取用戶域名
print(os.getenv("USERDOMAIN")) -- WIN10-JC
-- 獲取計(jì)算機(jī)名稱
print(os.getenv("COMPUTERNAME")) -- WIN10-JC
-- 獲取處理器cpu數(shù)量
print(os.getenv("NUMBER_OF_PROCESSORS")) -- 8
-- 獲取處理器CPU修訂號(hào)
print(os.getenv("PROCESSOR_REVISION")) -- 3c03
-- 獲取處理器CPU的型號(hào)
print(os.getenv("PROCESSOR_LEVEL")) -- 6
-- 獲取處理器CPU的架構(gòu)
print(os.getenv("PROCESSOR_ARCHITECTURE")) -- AMD64
-- 獲取處理器CPU標(biāo)識(shí)
print(os.getenv("PROCESSOR_IDENTIFIER")) -- Intel64 Family 6 Model 60 Stepping 3, GenuineIntel
-- 獲取命令行解釋器可執(zhí)行程序的完整路徑
print(os.getenv("COMSPEC")) -- C:\WINDOWS\system32\cmd.exe
print(os.getenv("ComSpec")) -- C:\WINDOWS\system32\cmd.exe
-- 獲取系統(tǒng)支持的文件擴(kuò)展名
print(os.getenv("PATHEXT")) -- .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
-- 獲取用戶主目錄的本地驅(qū)動(dòng)器(本地盤(pán)符)
print(os.getenv("HOMEDRIVE")) -- C:
-- 獲取系統(tǒng)根目錄
print(os.getenv("SystemRoot")) -- C:\WINDOWS
-- 獲取用戶配置文件路徑
print(os.getenv("ALLUSERSPROFILE")) -- C:\ProgramData
-- 獲取用戶主目錄完整路徑
print(os.getenv("HOMEPATH")) -- \Users\jc
-- 獲取系統(tǒng)臨時(shí)目錄完整路徑
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()
返回臨時(shí)文件名稱,自動(dòng)產(chǎn)生臨時(shí)文件并返回文件名如/tmp/sc9k,如果要使用,必須手動(dòng)打開(kāi)文件,最后不使用時(shí)必須手動(dòng)刪除。io.tmpfile()產(chǎn)生的臨時(shí)文件程序結(jié)束后會(huì)自動(dòng)刪除。
print(os.tmpname()) --\sc9k.
os.rename(oldname, newname)
更改文件或目錄名,若函數(shù)調(diào)用失敗則返回nil和錯(cuò)誤信息。
os.remove(filename)
刪除文件或空白目錄,若函數(shù)調(diào)用失敗則返回nil和錯(cuò)誤信息。
io庫(kù)
Lua I/O庫(kù)用于讀取和處理文件,提供兩套不同風(fēng)格的文件處理接口(模型),分為簡(jiǎn)單模式(和C語(yǔ)言一樣)和完全模式。
- 簡(jiǎn)單模式(simple model)
使用隱式的文件句柄,假設(shè)有一個(gè)當(dāng)前當(dāng)前輸入文件和一個(gè)當(dāng)前輸出文件,提供默認(rèn)輸入文件和輸出文件的操作。擁有一個(gè)當(dāng)前輸入文件和一個(gè)當(dāng)前輸出文件,提供針對(duì)這些文件相關(guān)的操作。
使用隱含的文件描述符,有操作設(shè)置默認(rèn)的輸入文件和輸出文件。
- 完全模式(complete model)
使用顯式文件句柄,使用外部的文件句柄來(lái)實(shí)現(xiàn),以面向?qū)ο蟮姆绞?,將所有文件操作定義為文件句柄的方法。
明確的操作描述符
使用明確的文件描述符時(shí),所有操作由表io提供,使之能夠在同一時(shí)間內(nèi)處理多個(gè)文件,功能相當(dāng)相似的隱式文件操作符。
-- 使用明確的文件描述符能夠在同一時(shí)間處理多個(gè)文件
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個(gè)與定義的文件描述符:
io.stderr 標(biāo)準(zhǔn)錯(cuò)誤輸出
io.stdin 標(biāo)準(zhǔn)輸入
io.stdout 標(biāo)準(zhǔn)輸出
io表調(diào)用方式
表io中提供三個(gè)和C語(yǔ)言中含義相同的預(yù)定義文件句柄:io.stdin、io.stdout、io.stderr。IO庫(kù)永遠(yuǎn)不會(huì)關(guān)閉這些文件。
使用io表,io.open()將返回指定文件的描述,且所有的操作將圍繞這個(gè)文件描述io表同樣提供3中預(yù)定義的文件描述:io.stdin、io.stdout、io.stderr。
- 文件句柄直接調(diào)用方式
使用file:xxx()函數(shù)方式進(jìn)行操作,其中file為ioi.open()返回的文件句柄,多數(shù)io函數(shù)調(diào)用失敗時(shí)返回nil和錯(cuò)誤信息。
除非另有說(shuō)明,IO函數(shù)在出錯(cuò)時(shí)都返回nil,第二個(gè)返回值為錯(cuò)誤消息,第三個(gè)返回值為系統(tǒng)相關(guān)的錯(cuò)誤代碼。成功時(shí)返回與nil不同的值。
簡(jiǎn)單模式
簡(jiǎn)單模式的所有操作都作用于兩個(gè)當(dāng)前文件,I/O庫(kù)將當(dāng)前輸入文件初始化為進(jìn)程標(biāo)準(zhǔn)輸入stdin,將當(dāng)前輸出文件初始化為進(jìn)程標(biāo)準(zhǔn)輸出stdout。
I/O庫(kù)會(huì)將標(biāo)準(zhǔn)輸入輸出作為其缺省的輸入文件和輸出文件,可通過(guò)io.input(filename)和io.output(filename)來(lái)改變當(dāng)前輸入輸出文件。
使用io.write()和io.read()從標(biāo)準(zhǔn)輸入stdin讀取輸出到標(biāo)準(zhǔn)輸出stdout,在執(zhí)行io.read()操作時(shí),會(huì)從標(biāo)準(zhǔn)輸入中讀取一行。使用io.input()和io.output()改變當(dāng)前文件。
io.input(filename)
以只讀模式打開(kāi)指定文件,并將其設(shè)定為當(dāng)前輸入文件,除非再次調(diào)用io.input(),否則所有的輸入都將來(lái)源于這個(gè)文件。
io.input([file])
相當(dāng)于io.input,但操作在默認(rèn)輸出文件上。使用文件名調(diào)用時(shí),以文本模式來(lái)打開(kāi)該名稱的文件,并將文件句柄設(shè)置為默認(rèn)輸入文件。若使用文件句柄去調(diào)用它,則簡(jiǎn)單地將句柄設(shè)置為默認(rèn)輸入文件。若調(diào)用時(shí)不傳入?yún)?shù)則返回當(dāng)前的默認(rèn)輸出文件。在出錯(cuò)的情況下,函數(shù)拋出錯(cuò)誤而非返回錯(cuò)誤碼。
io.output(filename)
在輸出方面,io.output()也可以完成類似的工作。
io.output([file])
使用文件名稱調(diào)用時(shí),以文本模式打開(kāi)該名稱的文件,并將文件句柄設(shè)置為默認(rèn)輸出文件。若使用文件句柄去調(diào)用它,就簡(jiǎn)單地將該句柄設(shè)置為默認(rèn)輸出和文件。若調(diào)用時(shí)不傳入?yún)?shù)則返回當(dāng)前的默認(rèn)輸出文件。
io.read()
io.read(...)
# 相當(dāng)于
io.input():read
按指定的格式讀取一個(gè)文件,按每個(gè)格式函數(shù)將返回一個(gè)字符串或數(shù)字,若不能正確地讀取將返回nil,若沒(méi)有指定格式將指默認(rèn)按行方式進(jìn)行讀取。
讀取格式
-
*a從當(dāng)前位置讀取整個(gè)文件,若為文件結(jié)尾EOF則返回空字符串。
io.read("*all")
讀取當(dāng)前輸入文件的所有內(nèi)容,以當(dāng)前位置作為開(kāi)始。若當(dāng)前位置處于文件末尾或文件為空則返回空字符串。由于Lua可以高效地處理長(zhǎng)字符串,因此在Lua中可先將數(shù)據(jù)從文件中完整讀出之后在通過(guò)字符串庫(kù)提供的函數(shù)進(jìn)行各種處理。
-
*l默認(rèn)選項(xiàng),讀取下一行的內(nèi)容,若為文件結(jié)尾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 ,以迭代器的形式訪問(wèn)文件中的每一行數(shù)據(jù)。
local lines = {}
-- 通過(guò)迭代器訪問(wèn)每行數(shù)據(jù)
for line in io.lines() do
lines[#lines+1] = line
end
-- 使用Lua標(biāo)準(zhǔn)庫(kù)table進(jìn)行排序
table.sort(lines)
for _,l in ipairs(lines) do
io.write(l, "\n")
end
返回當(dāng)前文件的下一行但不包含換行符,當(dāng)?shù)竭_(dá)文件末尾時(shí)則返回nil。
-
number讀取指定字節(jié)數(shù)的字符,若為文件結(jié)尾EOF則返回nil,若number為0則返回空字符串。
io.read("*number")
-- eg:讀取注釋中的數(shù)字
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
從當(dāng)前輸入文件中讀取一個(gè)數(shù)字,此時(shí)read將直接返回一個(gè)數(shù)字而非字符串。*number 選項(xiàng)會(huì)忽略數(shù)字前面所有的空格,且能處理像-3、+5.2這樣的數(shù)字格式。若當(dāng)前讀取的數(shù)據(jù)不合法則返回nil。調(diào)用時(shí)可指定多個(gè)選項(xiàng),函數(shù)會(huì)根據(jù)每個(gè)選項(xiàng)參數(shù)返回相應(yīng)的內(nèi)容。
-
*n讀取一個(gè)數(shù)字并返回它
-- 從輸入文件中最多讀取n個(gè)字符,若讀取不到任何字符則返回 nil,否則返回讀取到的字符串。
io.read(<num>)
-- eg
while true do
local block = io.read(2^13)
if not block then
break
end
io.write(block)
end
-- 特殊情況,用于檢查是否到達(dá)文件末尾,若尚未到達(dá)則返回空字符串否則返回 nil。
io.read(0)
io.write(...)
-- 將所有參數(shù)順序的寫(xiě)入到當(dāng)前輸出文件中
io.write(...)
-- 相當(dāng)于
io.output():write
-- eg:獲取任意數(shù)目的字符串參數(shù)并將其寫(xiě)入當(dāng)前標(biāo)準(zhǔn)輸出中
local t = io.write("sin(3)=", math.sin(3), "\n")
print("hello", "lua")
io.write與print不同之處在于,io.write不附加任何額外的字符到輸出中,例如制表符、換行符等。io.write是使用當(dāng)前輸出文件而print始終使用標(biāo)準(zhǔn)輸出。print會(huì)自動(dòng)調(diào)用參數(shù)的tostring方法,所以可以顯示出表、函數(shù)和nil。
io.open(filename [,mode])
按指定模式mode打開(kāi)一個(gè)文件,成功則返回新的文件句柄,失敗則返回nil和錯(cuò)誤信息。
文件模式
- r 默認(rèn)選項(xiàng),只讀模式,對(duì)已存在的文件的默認(rèn)打開(kāi)模式。
- w 可寫(xiě)模式,允許修改已存在的文件和創(chuàng)建新文件且不可讀取。
- a 追加模式,對(duì)于已存在的文件允許追加新內(nèi)容,但不允許修改原來(lái)內(nèi)容,同時(shí)也可以創(chuàng)建新文件。
- r+ 更新模式,之前數(shù)據(jù)將被保存。讀寫(xiě)模式,打開(kāi)已存在的文件。
- w+ 更新模式,之前數(shù)據(jù)將被清除。若文件已存在則刪除文件中的數(shù)據(jù),若文件不存在則創(chuàng)建文件,并以讀寫(xiě)模式打開(kāi)。
- a+ 添加更新模式,之前數(shù)據(jù)將被保存,僅允許在文件末尾進(jìn)行添加。以可讀的追加模式打開(kāi)已存在的文件,若文件不存在則新建文件。
- b 某些系統(tǒng)支持二進(jìn)制方式
-- 讀取指定文件
function getFile(filename)
local file = assert(io.open(filename, "r"))
local string = file:read("*all")
file:close()
return string
end
-- 按行方式讀取文件內(nèi)容
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
-- 以字符串方式寫(xiě)入文件
function writeFile(filename, string)
local file = assert(io.open(filename, "w"))
file:write(string)
file:close()
end
-- 控制臺(tái)寫(xiě)入字符串到文件
function writeConoleToFile(filename)
local file = assert(io.open(filename, "w"))
local string = io.read()
file:write(string)
file:close()
ene
io.popen([prog[, mode]])
開(kāi)始程序prog與額外的進(jìn)程,并返回用于prog的文件句柄,并不支持所有的系統(tǒng)平臺(tái)。
使用一個(gè)分離進(jìn)程開(kāi)啟程序program,返回的文件句柄可用于從這個(gè)程序中讀取數(shù)據(jù)(mode=r)或是向程序?qū)懭胼斎耄?code>mode=w)。
io.close(file)
io.close([file])
# 相當(dāng)于
file:close()
關(guān)閉默認(rèn)的輸出文件,當(dāng)文件句柄被垃圾收集后,文件將自動(dòng)關(guān)閉,句柄將變?yōu)橐粋€(gè)不可預(yù)知的值。
io.tmpfile()
返回一個(gè)臨時(shí)文件句柄,該文件以更新模式打開(kāi),程序結(jié)束時(shí)自動(dòng)刪除。
io.type(obj)
檢測(cè)obj是否為一個(gè)可用的文件句柄,若obj是一個(gè)打開(kāi)的文件句柄則返回字符串file,若obj是一個(gè)關(guān)閉的文件句柄則返回字符串close file。若obj不是句柄則返回nil。
返回值
-
file為一個(gè)打開(kāi)的文件句柄 -
close file為一個(gè)已關(guān)閉的文件句柄 -
nil表示obj不是一個(gè)文件句柄
io.flush()
io.flush()
# 相當(dāng)于
file:flush()
向文件寫(xiě)入緩沖中的所有數(shù)據(jù),輸出所有緩沖區(qū)中的內(nèi)容到默認(rèn)輸出文件。
io.lines(optional filename)
io.lines([filename])
提供一個(gè)循環(huán)迭代器以遍歷文件,若指定文件名則當(dāng)遍歷結(jié)束后將自動(dòng)關(guān)閉該文件,若使用默認(rèn)文件則遍歷結(jié)束后不會(huì)自動(dòng)關(guān)閉文件。
打開(kāi)指定的文件filename為讀模式并返回一個(gè)迭代函數(shù),每次調(diào)用將獲取文件中的一行內(nèi)容,當(dāng)?shù)竭_(dá)文件結(jié)尾時(shí),將返回nil并自動(dòng)關(guān)閉文件。
若不帶參數(shù)時(shí),io.lines()相當(dāng)于io.input():lines(),表示讀取默認(rèn)輸入設(shè)備的內(nèi)容但結(jié)束時(shí)不關(guān)閉文件。
返回一個(gè)迭代函數(shù),每次調(diào)用將獲得文件中的一行內(nèi)容,當(dāng)?shù)竭_(dá)文件結(jié)尾時(shí)將返回nil,但不關(guān)閉文件。
for line in io.lines("main.lua") do
print(line)
end
debug庫(kù)
Lua本身并未內(nèi)置調(diào)試器,提供了debug庫(kù)用于提供創(chuàng)建自定義調(diào)試器的功能。出于性能考慮,調(diào)用基本功能的正式接口都是通過(guò) C API提供,在Lua中訪問(wèn)debug庫(kù)的一種方式是通過(guò)Lua代碼直接訪問(wèn)。與其他庫(kù)不同的debug庫(kù)很多功能都會(huì)影響性能。其次,它打破了Lua中一些顛覆不破的真理,如在一個(gè)局部變量的作用域之外不能訪問(wèn)。
debug庫(kù)中的一種重要的思想是棧級(jí)別(stack level),一個(gè)棧級(jí)別就是一個(gè)指向在當(dāng)前時(shí)刻正在活動(dòng)的特殊函數(shù)的數(shù)字。也就是說(shuō),這個(gè)函數(shù)正在被調(diào)用但還沒(méi)有返回。調(diào)用debug庫(kù)的函數(shù)級(jí)別為1,調(diào)用它的函數(shù)級(jí)別為2,以此類推。
Lua的調(diào)試庫(kù)包含兩種函數(shù):自省函數(shù)(introspective functions)和鉤子(hooks)。自省函數(shù)可用來(lái)監(jiān)視一個(gè)正在運(yùn)行的程序的信息,如活動(dòng)函數(shù)的棧、當(dāng)前的執(zhí)行行、局部變量值和名稱等。鉤子可以跟蹤程序的運(yùn)行。自省函數(shù)主要是debug.getinfo。
自省函數(shù)
- debug.getinfo([thread,]func[,what]) 返回一個(gè)函數(shù)的信息表
- debug.traceback([thread,][message[, level]]) 獲取調(diào)用棧的回溯信息
debug.getinfo([thread,]func[,what])
debug.getinfo 參數(shù)
-
func可直接傳入函數(shù),也可傳入一個(gè)數(shù)值,此數(shù)值表示函數(shù)(運(yùn)行在指定線程)的調(diào)用棧深度,0表示getinfo自己,1表示調(diào)用getinfo的函數(shù),以此類推一般是2。若此數(shù)值大于活動(dòng)函數(shù)的深度返回nil。 -
what函數(shù)類型,若func是一個(gè)普通的Lua函數(shù)則為Lua,若func是一個(gè)C函數(shù)則為C,若是Lua主程序塊(chunk)部分則為main。
debug.getinfo 返回值是一個(gè)table包含以下字段
-
source函數(shù)定義的位置,若函數(shù)時(shí)通過(guò)loadstring在一個(gè)字符串中定義的,那么source就是這個(gè)字符串。若函數(shù)是在一個(gè)文件中定義的,那么source就是這個(gè)文件名加前綴@。 -
short_src是source的短版本,最多60個(gè)字符,可用于錯(cuò)誤信息匯總。 -
linedefined該函數(shù)定義的源代碼中第一行的行號(hào)
-- 獲取當(dāng)前棧的追溯信息
function traceback()
-- 獲取相應(yīng)棧層上函數(shù)的信息
for level=1,math.huge do
-- 獲取函數(shù)信息
-- S 選擇
-- source 函數(shù)定義的位置
-- short_src 函數(shù)定義位置的短版本,最多60個(gè)字符。
-- what 函數(shù)的類型
-- linedefined 函數(shù)定義在源代碼中第一行的行號(hào)
-- lastlinedefined 函數(shù)定義在源代碼中最后一行的行號(hào)
-- l 選擇
-- currentline 當(dāng)前所在行
local info = debug.getinfo(level, "Sl")
-- 判斷是否具有上層函數(shù)
if not info then
break
end
-- 判斷是否為一個(gè)C函數(shù)
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]])
獲取調(diào)用棧的回溯信息
debug.traceback參數(shù)
-
message字符串 可選項(xiàng) 被添加在?;厮菪畔⒌拈_(kāi)頭。 -
level數(shù)值 可選項(xiàng) 指明從棧的哪一層開(kāi)始回溯,默認(rèn)為1即調(diào)用traceback的位置。
若有message值且不是字符串或nil,traceback函數(shù)不做任何處理直接返回message,否則返回調(diào)用棧的回溯信息。
自定義的調(diào)試器
function __G__TRACKBACK__(errmsg)
print("LUA ERROR: "..tostring(errmsg).."\n")
print(debug.traceback("", 2))
end