Lua標(biāo)準(zhǔn)庫(kù)

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)
  • %X X表示任意非字母或數(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:plaintrue表示關(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ù)

數(shù)學(xué)庫(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)操作。

表庫(kù)
  • 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中。

操作系統(tǒng)庫(kù)

日期時(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.dateos.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.stdoutio.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)行操作,其中fileioi.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.writeprint不同之處在于,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_srcsource的短版本,最多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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容