Lua:何时以及如何将表写入
我正在从一本书中学习Lua,我不是程序员。我试图使用以下函数(直接从书中复制)将数据表保存到文件中,但该函数在尝试从_G[resTable]获取字符串时出错。为什么?Lua:何时以及如何将表写入,lua,global-variables,lua-table,Lua,Global Variables,Lua Table,我正在从一本书中学习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? l
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
这些函数不是泛化的“从/到任何文件读取/写入任何表”函数。它们显然希望全局表的名称作为参数,而不是[对本地]表本身的引用。它们看起来像是对书籍中经常出现的非常特定问题的一次性解决方案。:-)
你的函数不应该用_G做任何事情。我手头没有API引用,但是read循环应该做类似的事情
resTable[a] = line
写循环就可以了
hfile:write(resTable[i])
扔掉那个“本地”结果“还有桌子.:-) 此代码将文件中的数据读写到全局变量中,全局变量的名称在
aryTable
中指定。由于文件为空,readFromFile
实际上并不设置变量值。然后,writeToFile
在尝试获取变量值时失败,因为它们尚未设置
尝试将数据放入文件中,以便设置变量,或者在将变量写入文件之前自己设置变量值(例如,
Score=10
,等等)。显然,作者实现了一种将全局变量列表保存到文件并还原它们的方法
函数writeToFile
需要一个文件名和全局变量名列表(resTable
)。然后,它打开一个文件名以进行写入,并对提供的名称进行迭代:
for i=1, #resTable do
hfile:write(_G[resTable[i]])
end
在这个循环中,resTable[i]
是第i个名称,\u G[resTable[i]]
是对应的值,取自存储所有全局变量的表\u G
。如果未定义具有该名称的全局文件,\u G[resTable[i]
将返回nil
,这是您遇到故障的原因。因此,您必须提供一个可重新启动的
,其中填充了现有全局变量的名称,以避免此错误
除此之外,作者的序列化策略非常幼稚,因为它只处理具有字符串值的变量。事实上,通过像类型信息丢失一样将变量保存到文件中,一个值为“100”
(一个字符串)的变量和另一个值为100
(一个数字)的变量将同样存储在磁盘上
分析readFromFile
函数时,问题很明显。打开文件进行读取后,它会逐行扫描,为其可重启列表中提到的每个名称创建一个新变量:
local a = 1
for line in hfile:lines() do
_G[resTable[a]] = line
a = a + 1
end
问题有很多方面:
- 循环变量
line
将始终具有字符串值,因此重新创建的全局变量将是所有字符串,即使它们最初是数字李>
- 它假定变量以相同的顺序重新创建,因此您必须在保存文件时使用的
resTable
中提供相同的名称李>
- 它假设每行存储一个值,但这是错误的假设,因为
writeToFile
函数不会在每个值后写入换行符李>
此外,localresults={}
是无用的,在这两个函数中,文件句柄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脚本,并通过使用Luadofile
函数执行脚本将其读回。它的主要限制是只能保存字符串、布尔值和数字,但通常在学习时这就足够了
您可以使用以下语句对其进行测试:
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 )
如果您需要更高级的序列化技术,您可以参考。您的数据文件包含什么?当前“数据文件”没有任何内容…那么您希望readFromFile
做什么?函数writeToFile
无法将数据写入文件,当然,readToFile
必须读取nil。您可以使用Lua Pickle Table方法:是的,函数确实需要全局表的名称作为参数。这就是为什么作者在传递本地表作为参数时调用函数让我如此困惑的原因……而神秘的“结果”表也没有给我任何信心。作者在“readFromFile”背后的推理:在你的应用程序中,对于每个应用程序,您可能存储的变量数量可能不同。您永远不知道数据的保存顺序,如果保存或读取数据的顺序发生更改,则可能会出现错误变量中的值。所以,我们要做的是解决这个问题是有一个包含数据和文件名的表。这将为我们今后进一步扩大这一领域提供灵活性。然后,他显示了readFromFile
函数。您已经确定了作者写作的主要问题。在我看来很明显,在空数据文件上的readFromFile
存在问题,但在本章的任何一点上都没有