ファイルのクローズとエラー処理
ファイルハンドルを適切に閉じ、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) endI/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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- io.openによるファイルのオープン
- ファイル内容の読み込み
- ファイルへの書き込みと追記
- ファイルのクローズとエラー処理