การปิดไฟล์และการจัดการข้อผิดพลาด
ปิดตัวจัดการไฟล์อย่างถูกต้องและจัดการข้อผิดพลาดของ io ด้วย pcall
การปิดไฟล์และการจัดการข้อผิดพลาด เป็นบทเรียน Lua Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Lua Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน
ปิดไฟล์เสมอ
ไฟล์ทุกไฟล์ที่เปิดด้วย io.open ต้องปิดด้วย f:close() ไฟล์ที่ไม่ปิดจะทำให้ตัวระบุไฟล์รั่วไหล ตัวเก็บขยะของ Lua จะปิดไฟล์ให้ในภายหลัง แต่คุณอาจใช้เกินขีดจำกัดไฟล์ของ 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) endpcall เพื่อความปลอดภัยในการทำงานกับไฟล์
ห่อการทำงานกับไฟล์ด้วย 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การตรวจสอบว่าการเขียนสำเร็จ
บนระบบที่ดิสก์เต็มหรือมีปัญหาด้านสิทธิ์ f:write() อาจล้มเหลวได้แม้ว่า io.open จะทำงานสำเร็จแล้ว โปรดตรวจสอบค่าที่คืนจากการเขียนในส่วนการทำงานที่สำคัญ
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")รูปแบบ finally ด้วย pcall
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 (เช่น "ไม่พบไฟล์ดังกล่าว" หรือ "ถูกปฏิเสธสิทธิ์") โปรดใส่ข้อความข้อผิดพลาดในรายงานข้อผิดพลาดที่แสดงต่อผู้ใช้เสมอ
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 ที่มีเมธอด เมื่อแฮนเดิลถูกเก็บคืน ไฟล์จะถูกปิดโดยอัตโนมัติ อย่างไรก็ตาม อย่าพึ่งพาตัวเก็บขยะในการปิดไฟล์อย่างทันท่วงที ควรปิดไฟล์อย่างชัดเจนเสมอ คุณสามารถตรวจสอบว่าไฟล์ถูกปิดแล้วหรือไม่ด้วย 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 แม้จะเกิดข้อผิดพลาด คืออะไร
สรุป: การปิดไฟล์และการจัดการข้อผิดพลาด
สรุป:
- เรียก
f:close()อย่างชัดเจนเสมอ — อย่าพึ่งพาตัวเก็บขยะ - ห่อการทำงานกับ IO ด้วย pcall เพื่อการจัดการข้อผิดพลาดที่รัดกุม
- ใช้แม่แบบ "เปิด → pcall → ปิด"
- ใช้
os.remove/os.renameสำหรับการทำงานกับระบบไฟล์ - ตรวจสอบค่าที่คืนจากการเขียนในโค้ดส่วนสำคัญ
คำถามที่พบบ่อย
บทเรียน “การปิดไฟล์และการจัดการข้อผิดพลาด” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การปิดไฟล์และการจัดการข้อผิดพลาด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Lua Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การปิดไฟล์และการจัดการข้อผิดพลาด”
ปิดตัวจัดการไฟล์อย่างถูกต้องและจัดการข้อผิดพลาดของ io ด้วย pcall คุณปฏิบัติ Lua Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Lua Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Lua Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การปิดไฟล์และการจัดการข้อผิดพลาด” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Lua Academy นี้ได้ไหม
ได้ บทเรียน Lua Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การเปิดไฟล์ด้วย io.open
- การอ่านเนื้อหาไฟล์
- การเขียนและเพิ่มข้อมูลลงไฟล์
- การปิดไฟล์และการจัดการข้อผิดพลาด