Fi

File در Elixir

2 تمرین

درباره‌ی File

ماژول 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 استفاده کنید و این PID را به‌عنوان دستگاه 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"
ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

File را یاد بگیرید

تمرین کردن قفل شده است

برای تمرین File قفل 1 تمرین دیگر را باز کنید