0Pricing
Lua Academy · Aula

Fechando arquivos e tratando erros

Feche corretamente os identificadores de arquivos e trate erros de io com pcall.

Fechando arquivos e tratando erros é uma aula grátis de Lua Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Lua Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Lua Academy inclui 4 aulas no total.

Sempre Feche os Arquivos

Todo arquivo aberto com io.open deve ser fechado com f:close(). Arquivos não fechados causam vazamento de descritores de arquivo. O coletor de lixo do Lua acabará fechando-os, mas os limites de arquivos do OS podem ser esgotados antes que isso aconteça. Sempre feche o arquivo na função que o abriu.

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 para Segurança em E/S

Envolva as operações de arquivo em pcall para capturar erros inesperados (disco cheio, permissão negada durante a escrita). Isso garante que os erros sejam tratados de forma adequada, em vez de o programa simplesmente falhar.

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

Verificar o Sucesso da Escrita

Em sistemas com discos cheios ou problemas de permissão, f:write() pode falhar mesmo depois que io.open tiver sido executado com sucesso. Verifique o valor de retorno das operações de escrita em trechos críticos.

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")

Padrão finally com pcall

Lua não possui um bloco finally, mas pode simulá-lo com pcall. Envolva o código de risco em pcall; depois que pcall retornar (com sucesso ou falha), execute o código de limpeza incondicionalmente antes de relançar ou tratar o erro.

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)

Mensagens de Erro de io.open

io.open retorna nil, além de uma mensagem de erro do sistema e um código de erro. A mensagem inclui o caminho e o motivo do erro do OS ("Arquivo inexistente", "Permissão negada" etc.). Sempre inclua a mensagem de erro no relatório de erro para o usuário.

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

Identificador de Arquivo como Objeto

Um identificador de arquivo Lua é um userdata com métodos. Quando o identificador é coletado pelo coletor de lixo, o arquivo é fechado automaticamente. No entanto, não dependa do coletor de lixo para fechá-lo no momento certo — sempre feche-o explicitamente. Pode verificar se um arquivo está fechado com f:read() — isso gera um erro em um identificador fechado.

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]

Modelo para Processamento Seguro de Arquivos

Um modelo reutilizável para o processamento seguro de arquivos: abra com verificação de erro, processe com pcall e feche em todos os casos. Retorne resultados e erros de forma consistente usando a convenção nil+mensagem.

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) exclui um arquivo. os.rename(old, new) renomeia ou move um arquivo. Ambos retornam true em caso de sucesso ou nil, errMessage em caso de falha. Essas são as principais funções de manipulação do sistema de arquivos na Lua padrão.

-- 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 versus f:close

io.close(f) é equivalente a f:close(). io.close() sem argumento fecha o arquivo de saída padrão. Na maioria dos códigos, use f:close() para maior clareza.

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

Cópia Robusta de Arquivos

Uma cópia de arquivo adequada para produção, com tratamento de erros em cada etapa: abra a origem, abra o destino, copie em blocos, trate os erros de escrita e feche os dois arquivos.

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ção Rápida

Qual é a melhor maneira de garantir que um arquivo seja sempre fechado em Lua, mesmo que ocorra um erro?

Recapitulação: Fechamento e Tratamento de Erros

Resumo:

  • Sempre chame f:close() explicitamente — não dependa do coletor de lixo
  • Envolva a E/S em pcall para um tratamento robusto de erros
  • Use o modelo "abrir → pcall → fechar"
  • os.remove / os.rename para operações do sistema de arquivos
  • Verifique os valores de retorno das escritas no código crítico

Perguntas Frequentes

A aula “Fechando arquivos e tratando erros” é grátis?

Sim — o texto completo de “Fechando arquivos e tratando erros” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Lua Academy, atualize para CoddyKit PRO. O curso de Lua Academy inclui 4 aulas no total.

O que vou aprender em “Fechando arquivos e tratando erros”?

Feche corretamente os identificadores de arquivos e trate erros de io com pcall. Você pratica Lua Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Lua Academy?

Nenhuma experiência prévia é necessária. Lua Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Fechando arquivos e tratando erros”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Lua Academy?

Sim. Cada aula de Lua Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Abrindo arquivos com io.open
  2. Lendo o conteúdo de arquivos
  3. Escrevendo e acrescentando em arquivos
  4. Fechando arquivos e tratando erros
← Voltar para Lua Academy