Lua:何时以及如何将表写入_G

标签 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?
    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"在尝试 :write to _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 执行脚本来读取它们。功能。它的主要限制是它只能保存字符串、 bool 值和数字,但这通常在学习时就足够了。

    您可以使用以下语句对其进行测试:
    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 page on table serialization .

    关于Lua:何时以及如何将表写入_G,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19304987/

    相关文章:

    lua - 如何在 Lua 中使用本身就是表的唯一键来实现映射?

    inheritance - Lua中的子类构造函数方法

    Lua - 在 txt 文件中插入或删除字符串

    scala - 嵌套函数有效吗?

    javascript: namespace 污染

    function - 为什么清除传递的表在函数作用域内不起作用?

    lua - 尝试在脚本中索引一个 nil 值

    lua - Logitech 脚本,按住键直至松开

    javascript - 为什么我的 javascript 函数不抛出错误?

    architecture - 隐藏输入字段 vs session vs cookie