توفّر وحدة File الدوال اللازمة للتعامل مع الملفات.
لقراءة ملف كامل، استخدم File.read/1. وللكتابة إلى ملف، استخدم File.write/2.
توفّر الوحدة أيضًا دوال للملفات للنسخ والحذف وإعادة التسمية وغير ذلك. أسماؤها مشابهة لنظيراتها في UNIX، على سبيل المثال:
File.cp/3 - نسخ ملف.File.rm/1 - حذف ملف.File.rename/2 - إعادة تسمية ملف و/أو نقله.File.mkdir/1 - إنشاء مجلد.File.cwd/0 - الحصول على مجلد العمل الحالي.كل الدوال المذكورة من وحدة File لها أيضًا صيغة بـ ! تُطلق خطأً بدلًا من إرجاع صف خطأ (مثل File.read!/1). استخدم تلك الصيغة إذا كنت لا تنوي التعامل مع أخطاء مثل غياب الملفات أو نقص الأذونات.
File.read("does_not_exist")
# => {:error, :enoent}
File.read!("does_not_exist")
# => ** (File.Error) could not read file "does_not_exist": no such file or directory
# (elixir 1.10.4) lib/file.ex:353: File.read!/1
في كل مرة تُكتب فيها بيانات إلى ملف باستخدام File.write/2، يُفتح واصف ملف وتُنشأ عملية Elixir جديدة. ولهذا السبب، يُفضّل تجنّب الكتابة إلى ملف داخل حلقة باستخدام File.write/2.
بدلًا من ذلك، يمكن فتح ملف باستخدام File.open/2. الوسيط الثاني لـ File.open/2 هو مصفوفة أنماط، تتيح لك تحديد ما إذا كنت تريد فتح الملف للقراءة أو للكتابة.
الأنماط الشائعة الاستخدام هي:
:read - فتح للقراءة، يجب أن يكون الملف موجودًا:write - فتح للكتابة، سيُنشأ الملف إذا لم يكن موجودًا، وسيُستبدل المحتوى الموجود:append - فتح للكتابة، سيُنشأ الملف إذا لم يكن موجودًا، وسيُحتفظ بالمحتوى الموجودللاطلاع على قائمة شاملة بجميع الأنماط، راجع توثيق File.open/2.
تُرجع File.open/2 معرّف العملية (PID) للعملية التي تتعامل مع الملف. وللقراءة والكتابة إلى الملف، استخدم دوالًا من وحدة IO ومرّر معرّف العملية هذا كـ جهاز IO.
عند انتهائك من العمل على الملف، أغلقه باستخدام File.close/1.
file = File.open!("README.txt", [:write])
# => #PID<0.157.0>
IO.puts(file, "# README")
# => :ok
File.close(file)
# => :ok
قراءة ملف باستخدام File.read/1 ستُحمّل الملف كاملًا إلى الذاكرة دفعة واحدة. وقد يكون هذا مشكلة عند التعامل مع ملفات كبيرة جدًا. للتعامل معها بكفاءة، يمكنك استخدام File.open/2 وIO.read/2 لقراءة الملف سطرًا بسطر، أو يمكنك بثّ الملف باستخدام File.stream/3. يطبّق البثّ كلا البروتوكولين Enumerable وCollectable، ما يعني أنه يمكن استخدامه للقراءة والكتابة معًا.
File.stream!("file.txt")
|> Stream.map(&(&1 <> "!"))
|> Stream.into(File.stream!("new_file.txt"))
|> Stream.run()
تتطلب جميع الدوال التي تعمل على الملفات مسار ملف. يمكن أن تكون مسارات الملفات مطلقة أو نسبية إلى المجلد الحالي. للتعامل مع المسارات، استخدم دوالًا من وحدة Path. وللتوافق عبر المنصات، استخدم Path.join/1 لإنشاء المسارات. فهي ستختار الفاصل المناسب للمنصة.
Path.expand(Path.join(["~", "documents", "important.txt"]))
"/home/user/documents/important.txt"