المسارات
/
Elixir
Elixir
/
التمارين
/
فاحص الملفات
فاحص الملفات

فاحص الملفات

تمرين تعلّمي

مقدمة

الثنائيات

توفّر Elixir صياغة أنيقة للتعامل مع البيانات الثنائية، كما رأينا مع الصيغة الخاصة <<>> المخصّصة للتعامل مع السلاسل البتية.

النوع الثنائي هو تخصيص لنوع السلاسل البتية. فبينما يمكن أن تكون السلاسل البتية بأي طول (أي عدد من البتات)، فإن الثنائيات هي التي يمكن فيها قسمة عدد البتات على 8 دون باقٍ. أي أننا عند التعامل مع الثنائيات كثيرًا ما نفكّر في الأمور من حيث البايتات (8 بتات). ويمكن للبايت أن يمثّل أعدادًا صحيحة من 0 إلى 255. ومن الشائع التعامل مع قيم البايتات في النظام الست عشري، 0x00 - 0xFF.

تُعرَّف القيم الحرفية الثنائية باستخدام الصيغة الخاصة للسلاسل البتية <<>>. وعند تعريف قيمة حرفية ثنائية، يمكننا استخدام أعداد صحيحة وسلاسل نصية حرفية. الأعداد الصحيحة الأكبر من 255 ستتجاوز الحد، ولن يُستخدم منها إلا آخر 8 بتات. وبشكل افتراضي، يُطبَّق المعدّل ::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

لا تقلق بشأن قراءة الملف كبيانات ثنائية. افترض أن هذا قد تم نيابةً عنك، وأن الاختبارات تمرّره إليك كوسيط.

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 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.