0Pricing
Lua Academy · レッスン

ファイルのクローズとエラー処理

ファイルハンドルを適切に閉じ、pcallでioのエラーを処理します。

「ファイルのクローズとエラー処理」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

ファイルは必ず閉じる

io.openで開いたすべてのファイルは、f:close()で閉じる必要があります。閉じていないファイルはファイルディスクリプターを消費し続けます。LuaのGCはいずれファイルを閉じますが、GCが実行される前にOSのファイル数制限へ達する可能性があります。ファイルを開いた関数内で、必ず閉じてください。

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

I/Oの安全性のためのpcall

ファイル操作をpcallで囲むと、予期しないエラー(ディスク容量不足や書き込み途中の権限拒否など)を捕捉できます。これにより、プログラムをクラッシュさせず、エラーを適切に処理できます。

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

書き込みの成功を確認する

ディスク容量が不足しているシステムや権限に問題がある場合、io.openが成功した後でもf:write()が失敗することがあります。重要な処理では、書き込み操作の戻り値を確認してください。

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

pcallでfinallyパターンを実現する

Luaにはfinallyブロックがありませんが、pcallで同様の処理を実現できます。危険性のあるコードをpcallで囲み、pcallが成功または失敗を返した後、エラーを再送出または処理する前に、必ずクリーンアップコードを実行します。

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)

io.openからのエラーメッセージ

io.openはnilと、システムのエラーメッセージおよびエラーコードを返します。メッセージにはパスとOSのエラー理由("No such file"、"Permission denied"など)が含まれます。ユーザーへのエラーレポートには、必ずエラーメッセージを含めてください。

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

オブジェクトとしてのファイルハンドル

Luaのファイルハンドルは、メソッドを持つuserdataです。ハンドルがガベージコレクションの対象になると、ファイルは自動的に閉じられます。ただし、適切なタイミングで閉じられることをGCに頼らず、必ず明示的に閉じてください。ファイルが閉じているかどうかはf:read()で確認できます。閉じたハンドルに対してはエラーになります。

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]

安全なファイル処理のテンプレート

安全なファイル処理に再利用できるテンプレートは、エラーチェック付きで開き、pcallで処理し、どのような場合でも閉じるというものです。nil+メッセージの規約を使って、結果とエラーを一貫して返します。

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とos.rename

os.remove(path)はファイルを削除します。os.rename(old, new)はファイルの名前を変更または移動します。どちらも成功時はtrue、失敗時はnil, errMessageを返します。これらは、標準Luaにおける主なファイルシステム操作関数です。

-- 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とf:closeの違い

io.close(f)はf:close()と同等です。引数なしのio.close()は、デフォルトの出力ファイルを閉じます。ほとんどのコードでは、意図が明確になるf:close()を使用してください。

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

堅牢なファイルコピー

実運用に適したファイルコピーでは、各手順でエラーを処理します。具体的には、コピー元を開き、コピー先を開き、チャンク単位でコピーし、書き込みエラーを処理して、両方のファイルを閉じます。

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

確認問題

エラーが発生した場合でもLuaでファイルを必ず閉じるには、どの方法が最適ですか?

復習: ファイルのクローズとエラー処理

まとめ:

  • GCに頼らず、必ずf:close()を明示的に呼び出します
  • 堅牢なエラー処理のため、I/Oをpcallで囲みます
  • 「open → pcall → close」テンプレートを使用します
  • ファイルシステム操作にはos.remove / os.renameを使用します
  • 重要なコードでは書き込みの戻り値を確認します

よくある質問

「ファイルのクローズとエラー処理」レッスンは無料ですか?

はい。「ファイルのクローズとエラー処理」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「ファイルのクローズとエラー処理」で何を学びますか?

ファイルハンドルを適切に閉じ、pcallでioのエラーを処理します。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「ファイルのクローズとエラー処理」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. io.openによるファイルのオープン
  2. ファイル内容の読み込み
  3. ファイルへの書き込みと追記
  4. ファイルのクローズとエラー処理
← Lua Academyに戻る