1. 程式人生 > >Lua菜鳥教程學習筆記四(重難點 續)

Lua菜鳥教程學習筆記四(重難點 續)

內容會持續更新,有錯誤的地方歡迎指正,謝謝!

Lua 檔案 I/O

Lua I/O 庫用於讀取和處理檔案。分為簡單模式(和C一樣)、完全模式(以一種面對物件的形式,將所有的檔案操作定義為檔案控制代碼的方法)。如果同時讀取多個檔案的話,使用完全模式則較為合適。

簡單模式

以下為 file.lua 檔案程式碼,操作的檔案為test.lua(如果沒有你需要建立該檔案),程式碼如下:

-- 以只讀方式開啟檔案
file = io.open("test.lua", "r")
-- 設定預設輸入檔案為 test.lua
io.input(file)
-- 輸出檔案第一行
print(io.read())
-- 關閉開啟的檔案
io.close(file)

-- 以附加的方式開啟只寫檔案
file = io.open("test.lua", "a")
-- 設定預設輸出檔案為 test.lua
io.output(file)
-- 在檔案最後一行新增 Lua 註釋
io.write("--  test.lua 檔案末尾註釋")
-- 關閉開啟的檔案
io.close(file)

完全模式

通常我們需要在同一時間處理多個檔案。也就需要使用 file:function_name 來代替 io.function_name 。以下例項演示瞭如何同時處理同一個檔案:

-- 以只讀方式開啟檔案
file = io.open("test.lua", "r")
-- 輸出檔案第一行
print(file:read())
-- 關閉開啟的檔案
file:close()

-- 以附加的方式開啟只寫檔案
file = io.open("test.lua", "a")
-- 在檔案最後一行新增 Lua 註釋
file:write("--  test.lua 檔案末尾註釋")
-- 關閉開啟的檔案
file:close()

其中 io.read() 中我們沒有帶引數,引數可以是下表中的一個
在這裡插入圖片描述
簡單模式和完全模式read 的引數完全相同。

Lua 錯誤處理

語法錯誤

-- test.lua 檔案
a == 2
-- 以上程式碼執行結果為:
lua: test.lua:2: syntax error near '==' 
-- 2是第二行的意思,syntax error是語法錯誤的意思
for a= 1,10
   print(a)
end
-- 執行以上程式會出現如下錯誤:
lua: test2.lua:2: 'do' expected near 'print'

執行錯誤

編譯是可以成功的,但在執行的時候會產生錯誤:

function add(a,b)
   return a+b
end
add(10)

執行時,報錯如下:

lua: hello.lua:2: attempt to perform arithmetic on local 'b' (a nil value)
stack traceback:(堆疊資訊)
	hello.lua:2: in function 'add'
	hello.lua:4: in main chunk
	[C]: ?

錯誤處理

常用assert 和 error 來處理錯誤
1.assert檢查引數,若引數沒問題,assert不做任何事情;否則,assert以引數作為錯誤資訊丟擲。
assert舉例:assert(type(b) == "number", "b 不是一個數字") 當b不是數字時就輸出“lua: test.lua:1: b 不是一個數字”
2.error終止正在執行的函式,並返回message的內容作為錯誤資訊

Lua 除錯(Debug)

Lua 提供了 debug 庫用於提供建立我們自定義偵錯程式的功能。Lua 本身並未有內建的偵錯程式,但很多開發者共享了他們的 Lua 偵錯程式程式碼。
Lua 中 debug 庫包含了十多個函式,舉例如下:

function myfunction ()
print(debug.traceback("Stack trace"))
print(debug.getinfo(1))
print("Stack trace end")
    return 10
end
myfunction ()
print(debug.getinfo(1))
--  執行以上程式碼輸出結果為:

Stack trace
stack traceback:
    test2.lua:2: in function 'myfunction'
    test2.lua:8: in main chunk
    [C]: ?
table: 0054C6C8
Stack trace end

在上面這個例項中,我們用到了 debug 庫的 traceback 和 getinfo 函式, getinfo 函式用於返回函式資訊的表。

除錯型別

1.命令列除錯,命令列偵錯程式有:RemDebug、clidebugger、ctrace、xdbLua、LuaInterface - Debugger、Rldb、ModDebug
2.圖形介面除錯,圖形界偵錯程式有:SciTE、Decoda、ZeroBrane Studio、akdebugger、luaedit

Lua 垃圾回收

Lua 採用了自動記憶體管理,類似於GC。 這意味著你不用操心新建立的物件需要的記憶體如何分配出來, 也不用考慮在物件不再被使用後怎樣釋放它們所佔用的記憶體。
Lua 實現了一個增量標記-掃描收集器,它使用這兩個數字來控制垃圾收集迴圈: 垃圾收集器間歇率和垃圾收集器步進倍率。

  1. 垃圾收集器間歇率控制著收集器需要在開啟新的迴圈前要等待多久。 增大這個值會減少收集器的積極性。 當這個值比 100 小的時候,收集器在開啟新的迴圈前不會有等待。 設定這個值為 200 就會讓收集器等到總記憶體使用量達到之前的兩倍時才開始新的迴圈。
  2. 垃圾收集器步進倍率控制著收集器運作速度相對於記憶體分配速度的倍率。 增大這個值不僅會讓收集器更加積極,還會增加每個增量步驟的長度。 不要把這個值設得小於 100 , 那樣的話收集器就工作的太慢了以至於永遠都幹不完一個迴圈。 預設值是 200 ,這表示收集器以記憶體分配的"兩倍"速工作(每次 Lua 使用的記憶體翻倍時,就做一次完整的收集)。
    以下演示了一個簡單的垃圾回收例項:
mytable = {"apple", "orange", "banana"}
print(collectgarbage("count")) -- 以 K 位元組數為單位返回 Lua 使用的總記憶體數
mytable = nil
print(collectgarbage("count"))
print(collectgarbage("collect")) -- 做一次完整的垃圾收集循
print(collectgarbage("count"))

執行以上程式,輸出結果如下(注意記憶體使用的變化):

20.9560546875
20.9853515625
0
19.4111328125

Lua 面向物件

物件由屬性和方法組成。Lua中最基本的結構是table,所以需要用table來描述物件的屬性;Lua中的function可以用來表示方法。那麼Lua中的類可以通過table + function模擬出來。

以下我們演示了 Lua 面向物件的完整例項,包含建立物件,訪問屬性、成員函式,繼承等多個面向物件的知識點:

 -- Meta class
Shape = {area = 0}
-- 基礎類方法 new
function Shape:new (o,side)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  side = side or 0
  self.area = side*side;
  return o
end
-- 基礎類方法 printArea
function Shape:printArea ()
  print("面積為 ",self.area) -- 可以使用點號(.)來訪問類的屬性
end
-- 建立物件
myshape = Shape:new(nil,10) -- 建立物件是為類的例項分配記憶體的過程
myshape:printArea() -- 可以使用冒號 : 來訪問類的成員函式
--------------------------------------
Square = Shape:new()
-- 派生類方法 new
function Square:new (o,side)
  o = o or Shape:new(o,side)
  setmetatable(o, self)
  self.__index = self
  return o
end
-- 派生類方法 printArea
function Square:printArea ()
  print("正方形面積為 ",self.area)
end
-- 建立物件
mysquare = Square:new(nil,10)
mysquare:printArea()
--------------------------------------
Rectangle = Shape:new()
-- 派生類方法 new
function Rectangle:new (o,length,breadth)
  o = o or Shape:new(o)
  setmetatable(o, self)
  self.__index = self
  self.area = length * breadth
  return o
end
-- 派生類方法 printArea
function Rectangle:printArea ()
  print("矩形面積為 ",self.area)
end
-- 建立物件
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()

執行以上程式,輸出結果為:

面積為     100
正方形面積為     100
矩形面積為     200

總結:至於繼承,可以通過metetable模擬出來,但不推薦用,因為只需要模擬出最基本的物件,大部分時間都夠用了。

Lua 資料庫訪問

Lua 資料庫的操作庫:LuaSQL