[英]Lua: When and how to write tables to _G
我正在從書中學習Lua,而我不是程序員。 我正在嘗試使用以下函數(直接從本書中復制)將數據表保存到文件中,但是當嘗試從_G [resTable]獲取字符串時,該函數出錯。 為什么?
function readFromFile(filename,resTable)
local hfile = io.open(filename)
if hfile == nil then return end
local results = {} -why is this table here?
local a = 1
for line in hfile:lines() do-- debug shows this loop doesn't run (no lines in hfile?)
_G[resTable[a]] = line
a = a + 1
end
end
function writeToFile(filename, resTable)
local hfile = io.open(filename, "w")
if hfile == nil then return end
local i
for i=1, #resTable do
hfile:write(_G[resTable[i]])--bad argument #1 to 'write' (string expected, got nil)
end
end
'writeToFile'在嘗試執行以下操作時出錯:寫入_G [resTable [i]]。在此處列出的前兩個函數中,我不明白他們為什么引用_G [resTable [i]],因為我看不到任何寫入_G的代碼。
所以這是執行的順序:
local aryTable = {
"Score",
"Lives",
"Health",
}
readFromFile("datafile", aryTable)
writeToFile("datafile", aryTable)
我收到一個錯誤:
bad argument #1 to 'write' (string expected, got nil)
stack traceback:
[C]: in function 'write'
test.lua:45: in function 'writeToFile'
test.lua:82: in main chunk
顯然,作者已經實現了一種將全局變量列表保存到文件並恢復它們的方法。
函數writeToFile
需要一個文件名和一個全局變量名列表( resTable
)。 然后它打開一個用於編寫的文件名並迭代提供的名稱:
for i=1, #resTable do
hfile:write(_G[resTable[i]])
end
在這個循環中, resTable[i]
是第i個名稱, _G[resTable[i]]
是從表_G
獲取的相應值,它存儲了所有全局變量。 如果未定義具有該名稱的全局, _G[resTable[i]]
將返回nil
,這是您遇到失敗的原因。 因此,您必須提供一個填充了現有全局變量名稱的resTable
,以避免此錯誤。
除此之外,作者的序列化策略非常幼稚,因為它只處理帶有字符串值的變量。 實際上,通過將變量保存到文件中,類型信息會丟失,因此具有值"100"
(字符串)和另一個值為100
(數字)的變量將在磁盤上存儲相同。
分析readFromFile
函數時問題很明顯。 打開文件進行讀取后,它會逐行掃描,為其resTable
列表中提到的每個名稱創建一個新變量:
local a = 1
for line in hfile:lines() do
_G[resTable[a]] = line
a = a + 1
end
問題是多方面的:
line
始終具有字符串值,因此重新創建的全局變量將是所有字符串,即使它們最初是數字; resTable
提供相同的名稱; writeToFile
函數不會在每個值之后寫一個換行符; 此外, local results = {}
是無用的,並且在兩個函數中都不關閉文件句柄hfile
。 后者是非常糟糕的做法:它可能浪費系統資源,如果你的腳本失敗,所謂的寫入數據的一部分永遠不會進入磁盤,因為它可能仍然停留在某個緩沖區中。 腳本結束時,文件句柄會自動關閉,但前提是它以理智的方式結束。
除非你在粘貼代碼時遺漏了一些錯誤或者忽略了它的重要部分,或者本書正在逐步建立一些例子,我敢說它很糟糕。
如果你想快速而骯臟的方式來保存和檢索一些全局變量,你可以使用這個:
function writeToFile( filename, resTable )
local hfile = io.open(filename, "w")
if hfile == nil then return end
for _, name in ipairs( resTable ) do
local value = _G[name]
if value ~= nil then
hfile:write( name, " = ")
local vtype = type( value )
if vtype == 'string' then
hfile:write( string.format( "%q", value ) )
elseif vtype == 'number' or vtype == 'boolean' then
hfile:write( tostring( value ) )
else
-- do nothing - unsupported type
end
hfile:write( "\n" )
end
end
hfile:close()
end
readFromFile = dofile
它將全局變量保存為Lua腳本,並通過使用Lua dofile
函數執行腳本來讀取它們。 它的主要限制是它只能保存字符串,布爾數字,但通常這在學習時就足夠了。
您可以使用以下語句對其進行測試:
a = 10
b = "20"
c = "hello"
d = true
print( a, b, c, d )
writeToFile( "datafile", { "a", "b", "c", "d" } )
a, b, c, d = nil
print( a, b, c, d )
readFromFile( "datafile" )
print( a, b, c, d )
如果您需要更高級的序列化技術,可以參考表序列化的Lua WIKI頁面 。
這些不是通用的“從/向任何文件讀/寫任何表”功能。 他們顯然希望將全局表的名稱作為參數,而不是[對本地]表本身的引用。 它們看起來像是一種一次性解決方案,可以解決一個非常具體的問題,這些問題往往會出現在書本中。 :-)
你的函數不應該用_G做任何事情。 我沒有方便的API參考,但讀取循環應該做類似的事情
resTable[a] = line
而寫循環將會這樣做
hfile:write(resTable[i])
扔掉那個本地的“結果”表。 :-)
此代碼將文件中的數據讀寫到全局變量中,這些變量的名稱在aryTable
中指定。 由於您的文件為空,因此readFromFile
實際上並未設置變量值。 然后writeToFile
在嘗試獲取變量值時失敗,因為它們尚未設置。
嘗試將數據放入文件中以便設置變量,或者在將變量值寫入文件之前自己設置變量值(例如Score = 10
等)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.