По-видимому, автор реализовал способ экономии список глобальных переменных для их восстановления и восстановления.
Функция writeToFile
ожидает имя файла и список имен глобальных переменных (resTable
). Затем он открывает имя файла для записи и перебирает предоставленные названия:
for i=1, #resTable do
hfile:write(_G[resTable[i]])
end
в этом цикле resTable[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
функция. Его основное ограничение состоит в том, что он может сохранять только строки, boolean числа, но обычно этого достаточно, когда вы учитесь.
Вы можете протестировать его со следующими утверждениями:
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.
В чем состоит ваш файл данных? – interjay
В настоящее время «datafile» ничего не имеет – PHazer
... так что вы ожидаете от 'readFromFile'? – interjay