0Pricing
Lua Academy · Lezione

Chiusura dei file e gestione degli errori

Chiuda correttamente gli handle dei file e gestisca gli errori di io con pcall.

Chiusura dei file e gestione degli errori è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.

Chiudere sempre i file

Ogni file aperto con io.open deve essere chiuso con f:close(). I file non chiusi causano perdite di descrittori di file. Il garbage collector di Lua li chiuderà prima o poi, ma i limiti dei file del sistema operativo possono essere raggiunti prima dell'esecuzione del garbage collector. Chiuda sempre il file nella funzione che lo ha aperto.

local function readFile(path)
  local f, err = io.open(path, "r")
  if not f then return nil, err end
  local content = f:read("a")
  f:close()   -- always close
  return content
end

local data, err = readFile("config.txt")
if not data then print("Error:", err) end

pcall per la sicurezza dell'I/O

Racchiuda le operazioni sui file in pcall per intercettare gli errori imprevisti (disco pieno, autorizzazione negata durante una scrittura). In questo modo può gestire gli errori correttamente invece di causare l'arresto del programma.

local function safeCopy(src, dst)
  local ok, err = pcall(function()
    local f = io.open(src, "rb")
    if not f then error("Cannot open source: " .. src) end
    local content = f:read("a")
    f:close()
    local g = io.open(dst, "wb")
    if not g then error("Cannot open dest: " .. dst) end
    g:write(content)
    g:close()
  end)
  return ok, err
end

local ok, msg = safeCopy("input.txt", "output.txt")
if not ok then print("Failed:", msg) end

Verificare il successo della scrittura

Su sistemi con dischi pieni o problemi di autorizzazione, f:write() può non riuscire anche se io.open ha avuto successo. Verifichi il valore restituito dalle operazioni di scrittura nei percorsi critici.

local f = io.open("important.txt", "w")
if not f then
  print("Cannot create file")
  return
end

local ok, err = f:write("critical data\n")
if not ok then
  print("Write failed:", err)
  f:close()
  return
end

f:close()
print("Saved successfully")

Schema finally con pcall

Lua non dispone di un blocco finally, ma è possibile simularlo con pcall. Racchiuda il codice rischioso in pcall; dopo la restituzione di pcall (con successo o errore), esegua incondizionatamente il codice di pulizia prima di rilanciare o gestire l'errore.

local function withFile(path, mode, fn)
  local f, err = io.open(path, mode)
  if not f then return nil, err end
  local ok, result = pcall(fn, f)
  f:close()   -- always close, even on error
  if not ok then
    return nil, result
  end
  return result
end

local content, err = withFile("data.txt", "r", function(f)
  return f:read("a")
end)
print(content or err)

Messaggi di errore da io.open

io.open restituisce nil, un messaggio di errore di sistema e un codice di errore. Il messaggio include il percorso e il motivo dell'errore del sistema operativo ("No such file", "Permission denied" e così via). Includa sempre il messaggio di errore nella segnalazione mostrata all'utente.

local paths = {"config.txt", "missing.txt", "/root/secret.txt"}

for _, path in ipairs(paths) do
  local f, err, code = io.open(path, "r")
  if f then
    print(path, "-> ok, size:", f:seek("end"))
    f:close()
  else
    print(path, "-> ERROR:", err, "(code "..tostring(code)..")")
  end
end

L'handle del file come oggetto

Un handle di file Lua è un userdata con metodi. Quando l'handle viene raccolto dal garbage collector, il file viene chiuso automaticamente. Tuttavia, non faccia affidamento sul garbage collector per una chiusura tempestiva: chiuda sempre il file esplicitamente. Può verificare se un file è chiuso con f:read(): su un handle chiuso genera un errore.

local f = io.open("test.txt", "w")
f:write("test\n")

-- Explicit close
f:close()

-- After close, operations fail
local ok, err = pcall(function()
  f:read()   -- attempt to use closed file
end)
print(ok, err)   -- false  [closed file]

Modello per l'elaborazione sicura dei file

Un modello riutilizzabile per elaborare i file in sicurezza: aprire con verifica dell'errore, elaborare con pcall e chiudere in ogni caso. Restituisca risultati ed errori in modo coerente, usando la convenzione nil+messaggio.

local function processFile(path, processor)
  local f, err = io.open(path, "r")
  if not f then return nil, "open failed: " .. err end
  
  local ok, result = pcall(processor, f)
  f:close()
  
  if not ok then
    return nil, "processing failed: " .. result
  end
  return result
end

local lineCount, err = processFile("data.txt", function(f)
  local n = 0
  for _ in f:lines() do n = n + 1 end
  return n
end)
print(lineCount or err)

os.remove e os.rename

os.remove(path) elimina un file. os.rename(old, new) rinomina o sposta un file. Entrambe restituiscono true in caso di successo oppure nil, errMessage in caso di errore. Sono le principali funzioni del Lua standard per manipolare il file system.

-- Delete a file
local ok, err = os.remove("temp.txt")
if not ok then print("Remove failed:", err) end

-- Rename / move
ok, err = os.rename("old_name.txt", "new_name.txt")
if not ok then print("Rename failed:", err) end

-- Atomic update pattern
os.rename("config.new", "config.txt")

io.close e f:close

io.close(f) equivale a f:close(). io.close() senza argomenti chiude il file di output predefinito. Nella maggior parte del codice, usi f:close() per maggiore chiarezza.

local f = io.open("test.txt", "w")
f:write("hello\n")

-- Both are equivalent:
-- f:close()
io.close(f)

-- io.close() with no arg closes default output
io.output("out.txt")
io.write("to file\n")
io.close()   -- closes out.txt, restores stdout

Copia robusta dei file

Una copia di file adatta alla produzione, con gestione degli errori a ogni passaggio: apra il file di origine, apra la destinazione, copi a blocchi, gestisca gli errori di scrittura e chiuda entrambi i file.

local function copyFile(src, dst, chunkSize)
  chunkSize = chunkSize or 65536
  local fsrc, err1 = io.open(src, "rb")
  if not fsrc then return nil, err1 end
  local fdst, err2 = io.open(dst, "wb")
  if not fdst then fsrc:close(); return nil, err2 end
  
  local ok = true
  local chunk = fsrc:read(chunkSize)
  while chunk and ok do
    local w, werr = fdst:write(chunk)
    if not w then ok = false; err2 = werr end
    chunk = fsrc:read(chunkSize)
  end
  fsrc:close(); fdst:close()
  if not ok then os.remove(dst); return nil, err2 end
  return true
end

Verifica rapida

Qual è il modo migliore per assicurarsi che un file venga sempre chiuso in Lua, anche se si verifica un errore?

Riepilogo: chiusura e gestione degli errori

Riepilogo:

  • Chiami sempre esplicitamente f:close(): non faccia affidamento sul garbage collector
  • Racchiuda l'I/O in pcall per una gestione robusta degli errori
  • Usi il modello "open → pcall → close"
  • os.remove / os.rename per le operazioni sul file system
  • Verifichi i valori restituiti dalle scritture nel codice critico

Domande Frequenti

La lezione «Chiusura dei file e gestione degli errori» è gratuita?

Sì — il testo completo di «Chiusura dei file e gestione degli errori» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.

Cosa imparerò in «Chiusura dei file e gestione degli errori»?

Chiuda correttamente gli handle dei file e gestisca gli errori di io con pcall. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Lua Academy?

Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Chiusura dei file e gestione degli errori»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Lua Academy?

Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Apertura dei file con io.open
  2. Lettura del contenuto dei file
  3. Scrittura e aggiunta ai file
  4. Chiusura dei file e gestione degli errori
← Torna a Lua Academy