إغلاق الملفات ومعالجة الأخطاء
أغلِق مقابض الملفات بطريقة صحيحة وعالج أخطاء io باستخدام pcall
إغلاق الملفات ومعالجة الأخطاء درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
أغلقوا الملفات دائمًا
يجب إغلاق كل ملف يُفتح باستخدام io.open عبر f:close(). فالملفات غير المغلقة تسرّب واصفات الملفات. وسيغلقها جامع البيانات المهملة في Lua في النهاية، لكن يمكنكم استنفاد حدود ملفات نظام التشغيل قبل تشغيل جامع البيانات المهملة. أغلقوا الملف دائمًا في الدالة التي فتحته.
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 لأمان عمليات الإدخال والإخراج
غلّفوا عمليات الملفات داخل 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، بالإضافة إلى رسالة خطأ من النظام ورمز الخطأ. وتتضمن الرسالة المسار وسبب الخطأ من نظام التشغيل (مثل "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 يحتوي على أساليب. وعند جمع المقبض بواسطة جامع البيانات المهملة، يُغلق الملف تلقائيًا. ومع ذلك، لا تعتمدوا على جامع البيانات المهملة للإغلاق في الوقت المناسب؛ أغلقوا الملف صراحةً دائمًا. ويمكنكم التحقق مما إذا كان الملف مغلقًا باستخدام 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+message.
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()صراحةً دائمًا، ولا تعتمدوا على GC - غلّفوا عمليات الإدخال والإخراج في pcall لمعالجة الأخطاء بمتانة
- استخدموا قالب "open → pcall → close"
- استخدموا
os.removeوos.renameلعمليات نظام الملفات - تحققوا من القيم المعادة من عمليات الكتابة في الكود الحرج
الأسئلة الشائعة
هل درس «إغلاق الملفات ومعالجة الأخطاء» مجاني؟
نعم — نص درس «إغلاق الملفات ومعالجة الأخطاء» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «إغلاق الملفات ومعالجة الأخطاء»؟
أغلِق مقابض الملفات بطريقة صحيحة وعالج أخطاء io باستخدام pcall تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «إغلاق الملفات ومعالجة الأخطاء»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- فتح الملفات باستخدام io.open
- قراءة محتويات الملفات
- الكتابة إلى الملفات وإلحاق البيانات بها
- إغلاق الملفات ومعالجة الأخطاء