يشرح هذا الدليل كيفية استخراج امتداد الملف في Java باستخدام أمثلة عملية. ستتعلم قراءة الامتداد من اسم ملف أو مسار كامل، والتعامل مع أكثر من نقطة والملفات المخفية، ثم استعراض امتدادات ملفات مجلد. نوضح أيضًا الفرق بين امتداد الاسم ونوع المحتوى، وكيفية تجنب أخطاء الفهرسة وحدود المسارات.
ما هو امتداد الملف؟
الامتداد هو الجزء الذي يأتي غالبًا بعد آخر نقطة في اسم الملف، مثل java في Main.java أو png في photo.png. تستخدمه أنظمة التشغيل والبرامج كإشارة إلى نوع الملف، لكنه لا يثبت أن البيانات فعلًا من هذا النوع. لذلك لا تعتمد عليه وحده عند التحقق الأمني من ملف مرفوع إلى موقع أو تطبيق.
استخراج الامتداد من اسم باستخدام String
لدينا اسم ملف بسيط، ويمكن استخدام lastIndexOf للعثور على آخر نقطة ثم substring لقراءة ما بعدها. الكود يعيد نصًا فارغًا إذا لم يجد امتدادًا واضحًا:
public class FileExtensionExample {
static String getExtension(String name) {
if (name == null) return "";
int dot = name.lastIndexOf('.');
if (dot <= 0 || dot == name.length() - 1) return "";
return name.substring(dot + 1).toLowerCase();
}
public static void main(String[] args) {
System.out.println(getExtension("Main.java"));
System.out.println(getExtension("archive.tar.gz"));
System.out.println(getExtension("README"));
}
}يطبع المثال java ثم gz ثم سلسلة فارغة. استخدام آخر نقطة يجعل archive.tar.gz امتداده الأخير gz. حولنا الأحرف إلى صغيرة كي لا يختلف PDF عن pdf عند المقارنة. وفحصنا null والنقطة الأولى والنقطة الأخيرة لتجنب نتائج مربكة أو خطأ أثناء التنفيذ.
كيف نتعامل مع الملفات المخفية؟
قد يبدأ الاسم بنقطة مثل .env أو .gitignore. حسب القاعدة المستخدمة هنا يعيد الكود امتدادًا فارغًا، لأن النقطة هي الحرف الأول وليست فاصلًا بين اسم وامتداد. يمكن لتطبيقك اختيار قاعدة مختلفة، لكن ينبغي أن توثقها وتختبرها. كذلك الاسم document. ينتهي بنقطة ولا يحتوي نصًا بعدها، لذلك يرجع قيمة فارغة.
استخراج الامتداد من مسار باستخدام Path
عندما يكون لديك مسار كامل، افصل اسم الملف عن المجلد باستخدام Path. هذا أفضل من تقسيم المسار يدويًا على الشرطة المائلة، لأن شكل الفاصل يختلف بين الأنظمة:
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathExtensionExample {
static String extension(Path path) {
if (path == null || path.getFileName() == null) return "";
String name = path.getFileName().toString();
int dot = name.lastIndexOf('.');
if (dot <= 0 || dot == name.length() - 1) return "";
return name.substring(dot + 1).toLowerCase();
}
public static void main(String[] args) {
Path file = Paths.get("documents", "report.final.PDF");
System.out.println(extension(file));
}
}تكون النتيجة pdf. إذا لم يشِر المسار إلى اسم ملف، قد تكون قيمة getFileName فارغة؛ لهذا تحققنا منها قبل استدعاء toString. استخدم المسارات النسبية أو المطلقة وفق بنية مشروعك، ولا تفترض وجود الملف لمجرد إنشاء كائن Path، إذ إن Path لا يقرأ الملف تلقائيًا.
عرض امتدادات ملفات مجلد
يمكن استخدام Files.list لاستعراض العناصر الموجودة في مجلد. نغلق التدفق باستخدام try-with-resources، ونفحص أن العنصر ملف عادي قبل طباعة امتداده:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class DirectoryExtensions {
public static void main(String[] args) {
Path folder = Paths.get("documents");
try (Stream<Path> paths = Files.list(folder)) {
paths.filter(Files::isRegularFile).forEach(path -> {
String name = path.getFileName().toString();
int dot = name.lastIndexOf('.');
String ext = dot > 0 && dot < name.length() - 1
? name.substring(dot + 1).toLowerCase() : "بدون امتداد";
System.out.println(name + " : " + ext);
});
} catch (IOException e) {
System.err.println("تعذر قراءة المجلد: " + e.getMessage());
}
}
}تستبعد Files::isRegularFile المجلدات الفرعية. إذا أردت المرور داخل مجلدات فرعية، استخدم Files.walk وحدد عمقًا يناسب التطبيق. قد تفشل القراءة بسبب عدم وجود المسار أو الصلاحيات، لذا نتعامل مع IOException بدل افتراض نجاح العملية.
حالات اختبار مهمة
- اسم عادي بامتداد واحد مثل image.jpg.
- اسم يحوي نقاطًا متعددة مثل backup.2026.tar.gz.
- اسم بلا نقطة مثل README.
- اسم مخفي يبدأ بنقطة مثل .config.
- اسم ينتهي بنقطة مثل document.
- اسم null أو مسار يشير إلى مجلد بلا اسم ملف.
اختبر هذه الحالات في وحدة منفصلة قبل ربط الدالة برفع الملفات. قد تفضل إرجاع Optional<String> بدل نص فارغ إذا أردت التمييز الصريح بين وجود امتداد وغيابه. اختر واجهة واحدة للنتيجة واجعل سلوكها واضحًا للمستخدم.
الفرق بين الامتداد ونوع MIME
الامتداد جزء من الاسم، أما نوع MIME مثل image/png أو text/plain فيصف طريقة تفسير المحتوى في الويب. لا يعني وجود امتداد png أن الملف صورة سليمة؛ يمكن تغيير الاسم دون تغيير البيانات. عند استقبال ملفات من المستخدمين، افحص المحتوى باستخدام مكتبة أو آلية موثوقة، وطبّق قيود الحجم والصلاحيات على الخادم، ولا تمنح الملف المرفوع صلاحيات تنفيذية لمجرد امتداده.
أخطاء شائعة
من الأخطاء استعمال indexOf بدل lastIndexOf، مما يعطي نتيجة خاطئة عندما يحتوي الاسم نقاطًا متعددة. كما أن split(“.”) يحتاج تعاملًا صحيحًا مع التعبيرات النمطية، وقد ينتج أجزاء فارغة عند النقطة الأخيرة. لا تحلل المسار كاملًا باعتباره اسم ملف؛ افصل اسم الملف أولًا عبر Path. ولا تنس فحص null قبل استخدام الدوال. توحيد حالة الأحرف مناسب غالبًا، لكن احتفظ بالاسم الأصلي إذا كنت تعرضه كما رفعه المستخدم.
أسئلة شائعة
هل يعيد المثال النقطة مع الامتداد؟
لا، يعيد النص الذي يلي النقطة مثل java. إذا احتجت النقطة، أضفها عند تنسيق العرض.
هل يوفر Path دالة جاهزة للامتداد؟
لا، Path يوفر التعامل مع المسار واسم الملف، لكن قاعدة الامتداد تختلف حسب التطبيق، لذا يستخرجها البرنامج من الاسم.
تابع دروس Java، واقرأ أيضًا شرح Selection Sort في Java ودرس البحث الثنائي للتوسع في أمثلة البرمجة والخوارزميات.





