مسیرها
/
Elixir
Elixir
/
تمرین‌ها
/
شناساگر فایل
شناساگر فایل

شناساگر فایل

تمرین یادگیری

مقدمه

داده‌ی دودویی

الیکسیر برای کار با داده‌های دودویی شکل نگارشی زیبایی در اختیارمان می‌گذارد؛ همان‌طور که در فرم ویژه‌ی <<>> که برای کار با «رشته‌های بیت» فراهم شده است دیده‌ایم.

نوع «دودویی» حالت خاصی از نوع «رشته‌ی بیت» است. رشته‌های بیت می‌توانند هر طولی داشته باشند (هر تعداد بیت)، حال آنکه در دودویی‌ها تعداد بیت‌ها بر ۸ بخش‌پذیر است. یعنی هنگام کار با دودویی‌ها معمولاً در قالب «بایت» (۸ بیت) به داده‌ها نگاه می‌کنیم. یک بایت می‌تواند اعداد صحیحی از 0 تا 255 را نمایش دهد. کار با مقدارهای بایتی در مبنای شانزده رایج است، مثل 0x00 - 0xFF.

لیترال‌های دودویی با فرم ویژه‌ی رشته‌ی بیت <<>> تعریف می‌شوند. هنگام تعریف یک لیترال دودویی، می‌توانیم از لیترال‌های عددی و رشته‌ای استفاده کنیم. مقدارهای عددی بزرگ‌تر از ۲۵۵ سرریز می‌شوند و تنها ۸ بیت آخر عدد به کار می‌رود. به‌طور پیش‌فرض، اصلاح‌گر ::binary روی مقدار اعمال می‌شود. می‌توانیم دودویی‌ها را با عملگر <>/2 به هم بچسبانیم.

<<255>> == <<0xFF>>
# Overflowing bits are truncated
<<256>> == <<0>>
<<2, 4, 6, 8, 10, 12, 14, 16>> == <<0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10>>

«بایت تهی» نام دیگری برای <<0>> است.

تطبیق الگو روی داده‌های دودویی

تطبیق الگو حتی به دودویی‌ها هم گسترش یافته است و می‌توانیم روی بخشی از داده‌های دودویی تطبیق الگو انجام دهیم، درست همان‌طور که این کار را برای یک لیست انجام می‌دادیم.

# Ignore the first 8 bytes, match and bind the remaining to `body`
<<_::binary-size(8), body::binary>>

مثل سایر انواع تطبیق الگو، می‌توانیم از این قابلیت در امضای توابع هم استفاده کنیم و هنگام انتخاب از میان چند بند تابع، تطبیق الگو انجام دهیم.

دستورالعمل‌ها

شما روی پروژه‌ای کار می‌کنید که به کاربران اجازه می‌دهد فایل‌ها را روی سرور بارگذاری کنند تا با کاربران دیگر به اشتراک گذاشته شود. به شما سپرده شده است که تابعی بنویسید که بررسی کند یک فایل بارگذاری‌شده با نوع رسانه آن مطابقت دارد یا نه. کمی تحقیق می‌کنید و متوجه می‌شوید که چند بایت اول یک فایل معمولاً مخصوص همان نوع فایل است و به آن نوعی امضا می‌دهد.

برای مرجع از جدول زیر استفاده کنید:

نوع فایل پسوند رایج نوع رسانه «امضای دودویی»
ELF "exe" "application/octet-stream" 0x7F, 0x45, 0x4C, 0x46
BMP "bmp" "image/bmp" 0x42, 0x4D
PNG "png" "image/png" 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
JPG "jpg" "image/jpg" 0xFF, 0xD8, 0xFF
GIF "gif" "image/gif" 0x47, 0x49, 0x46

1. با داشتن یک پسوند، نوع رسانه‌ی مورد انتظار را برگردانید

تابع type_from_extension/1 را پیاده‌سازی کنید. این تابع باید یک پسوند فایل (رشته) بگیرد و نوع رسانه (رشته) یا nil را برگرداند، اگر پسوند با پسوندهای مورد انتظار مطابقت نداشته باشد.

FileSniffer.type_from_extension("exe")
# => "application/octet-stream"

FileSniffer.type_from_extension("txt")
# => nil

2. با داشتن یک فایل دودویی، نوع رسانه‌ی مورد انتظار را برگردانید

تابع type_from_binary/1 را پیاده‌سازی کنید. این تابع باید یک فایل (دودویی) بگیرد و نوع رسانه (رشته) یا nil را برگرداند، اگر امضای فایل با امضاهای مورد انتظار مطابقت نداشته باشد.

file = File.read!("application.exe")
FileSniffer.type_from_binary(file)
# => "application/octet-stream"

file = File.read!("example.txt")
FileSniffer.type_from_binary(file)
# => nil

نگران خواندن فایل به‌صورت دودویی نباشید. فرض کنید این کار پیشاپیش برای شما انجام شده است و tests آن را به‌عنوان آرگومان در اختیار شما قرار می‌دهند.

3. با داشتن یک پسوند و یک فایل دودویی، بررسی کنید که فایل با نوع مورد انتظار مطابقت دارد

تابع verify/2 را پیاده‌سازی کنید. این تابع باید یک فایل (دودویی) و یک پسوند (رشته) بگیرد و یک تاپل :ok یا :error برگرداند.

file = File.read!("application.exe")

FileSniffer.verify(file, "exe")
# => {:ok, "application/octet-stream"}

FileSniffer.verify(file, "png")
# => {:error, "Warning, file format and file extension do not match."}
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Elixir Exercism

آماده‌اید شناساگر فایل را شروع کنید؟

در Exercism ثبت‌نام کنید تا Elixir را همراه با 58 مفهوم168 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.