A quanto pare l'autore ha messo in atto un modo di salvare un elenco di variabili globali da archiviare e ripristinare.
La funzione writeToFile
prevede un nome file e un elenco di nomi di variabili globali (resTable
). Poi si apre un nome file per la scrittura e itera sui nomi forniti:
for i=1, #resTable do
hfile:write(_G[resTable[i]])
end
in questo ciclo resTable[i]
è il nome i-esimo e _G[resTable[i]]
è il valore corrispondente, preso dalla tabella _G
, che memorizza tutte le variabili globali . Se un globale con quel nome non è definito, _G[resTable[i]]
restituirà nil
, che è la causa dell'errore riscontrato. Pertanto, è necessario fornire un numero resTable
riempito con nomi di valori globali esistenti per evitare questo errore.
Oltre a ciò, la strategia di serializzazione dell'autore è davvero ingenua, poiché gestisce solo le variabili con valori stringa.Infatti salvando le variabili in un file come quello si perde l'informazione sul tipo, quindi una variabile avente il valore "100"
(una stringa) e un'altra con il valore 100
(un numero) verranno memorizzate sullo stesso disco.
Il problema è evidente analizzando la funzione readFromFile
. Dopo aver aperto il file per la lettura, la scansione riga per riga, la creazione di una nuova variabile per ogni nome citato nella sua lista resTable
:
local a = 1
for line in hfile:lines() do
_G[resTable[a]] = line
a = a + 1
end
il problema è molteplice:
- il ciclo variabile
line
volontà hanno sempre un valore stringa, quindi le globali ricreate saranno tutte stringhe, anche se originariamente erano numeri;
- presuppone che le variabili vengano ricreate nello stesso ordine, pertanto è necessario fornire gli stessi nomi in
resTable
utilizzati quando si è salvato il file;
- presuppone che i valori siano memorizzati uno per riga, ma questa è una falsa ipotesi, poiché la funzione
writeToFile
non scrive un carattere di fine riga dopo ogni valore;
Inoltre che local results = {}
è inutile e in entrambe le funzioni il file handle hfile
non è chiuso. Quest'ultima è una pratica molto scorretta: potrebbe sprecare risorse di sistema e se il tuo script fallisce, parte dei dati presumibilmente scritti non potrebbero mai arrivare al disco, poiché potrebbe essere ancora bloccato in qualche buffer. Gli handle di file si chiudono automaticamente al termine dello script, ma solo se termina in modo corretto.
A meno che non abbiate commesso qualche errore nell'incollare il codice o omesso parti significative di esso o che il libro stia costruendo qualche esempio in modo incrementale, oserei dire che è piuttosto schifoso.
Se volete un modo rapido e sporco per salvare e recuperare alcune variabili globali è possibile utilizzare questo:
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
Si risparmia le variabili globali come uno script Lua e li rilegge eseguendo lo script utilizzando Lua dofile
funzione. Il suo limite principale è che può solo salvare stringhe, booleane un numero, ma di solito questo è sufficiente durante l'apprendimento.
È possibile verificare con le seguenti affermazioni:
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)
Se avete bisogno di tecniche di serializzazione più avanzate è possibile fare riferimento a Lua WIKI page on table serialization.
Che cosa contiene il file di dati? – interjay
attualmente "datafile" non ha nulla – PHazer
... quindi cosa ci si aspetta da 'readFromFile'? – interjay