كيفية قراءة ملف نصي من مجلد resources في Kotlin: برنامج تعليمي خطوة بخطوة
\n\nمرحباً يا صديقي! إذا كنت قد كتبت يوماً ما بلغة Kotlin لتطبيقات Android أو ببساطة قمت بإنشاء تطبيق وحدة تحكم، فبالتأكيد واجهت مهمة بسيطة ولكنها خادعة: كيف تقرأ ملفاً نصياً موجوداً في مجلد resources؟ قد يبدو الأمر بسيطاً، ولكن إذا ألقيت نظرة على Stack Overflow، فإن السؤال "How to read a text file from resources in Kotlin?" يحقق آلاف المشاهدات. هذا يعني أن المشكلة حقيقية.
في هذه المقالة، سنستعرض 5 طرق موثوقة للقيام بذلك. ستتعرف على الفرق بين javaClass و ClassLoader، وكيفية تجنب الوقوع في NullPointerException، وماذا تفعل إذا كان مشروعك عبارة عن مكتبة وليس تطبيقاً. هيا بنا!
1. التحضير: أين نضع الملف؟
\nقبل القراءة، يجب وضع الملف في المكان الصحيح. في مشروع Kotlin القياسي (Gradle, Maven)، يوجد مجلد الموارد عادةً هنا:
\n\nsrc/main/resources/\n\nللاختبارات — src/test/resources/. إذا كان لديك مشروع Android، توضع الموارد في src/main/res/raw/ (ولكن هناك منطق خاص بها، سنتحدث عنه لاحقاً). سنركز هنا على Kotlin/JVM الخالص.
لنقم بإنشاء ملف بسيط data.txt بمحتوى:
مرحباً بالعالم!\nهذه أسطر من الموارد.\nKotlin هو الأفضل.\n\nممتاز، الأداة جاهزة. الآن دعنا نرى كيفية فتحه.
\n\n2. الطريقة رقم 1: الطريقة التقليدية عبر javaClass
\nالطريقة الأكثر شيوعاً وبديهية هي استخدام javaClass (وهي غلاف Kotlin لـ getClass() في Java).
import java.io.File\n\nfun readFromResources(fileName: String): String {\n val inputStream = this::class.java.classLoader?.getResourceAsStream(fileName)\n ?: throw IllegalArgumentException("الملف $fileName غير موجود في الموارد")\n return inputStream.bufferedReader().readText()\n}\n\nتحليل الكود:
\n- \n
this::class.java— نحصل على فئة Java للكائن الحالي. \n .classLoader— نأخذ ClassLoader (محمل الفئات). \n getResourceAsStream(fileName)— نفتح تياراً. \n - عامل إلفيس
?:يلقي استثناءً إذا لم يتم العثور على الملف. \n
نقوم بالاستدعاء:
\nfun main() {\n val content = readFromResources("data.txt")\n println(content)\n}\n\nعند الإخراج سنرى ثلاثة أسطر من ملفنا. بسيط وأنيق.
\n\n3. الطريقة رقم 2: استخدام object للأدوات المساعدة
\nإذا كنت تكتب فئة أدوات مساعدة، فمن المناسب وضع المنطق في object (مفرد). في Kotlin يتم ذلك كالتالي:
object ResourceReader {\n fun readText(fileName: String): String {\n val stream = ResourceReader::class.java.classLoader\n .getResourceAsStream(fileName)\n ?: throw FileNotFoundException("الموارد $fileName غير موجودة")\n return stream.bufferedReader().readText()\n }\n}\n\n// الاستخدام:\nfun main() {\n val text = ResourceReader.readText("config.json")\n println(text)\n}\n\nلاحظ: نحن نستخدم ResourceReader::class.java — هذا يعمل لأن object هو مفرد وله فئة.
4. الطريقة رقم 3: القراءة كـ URL (للحصول على المسار)
\nأحياناً نحتاج ليس إلى المحتوى، بل إلى مسار الملف (مثلاً لتمريره إلى مكتبة أخرى). في هذه الحالة نستخدم getResource():
fun getResourcePath(fileName: String): String {\n val url = this::class.java.classLoader.getResource(fileName)\n ?: throw RuntimeException("الموارد $fileName غير موجودة")\n return url.path\n}\n\nولكن كن حذراً: إذا كان المشروع مضغوطاً في JAR، فقد يشير url.path إلى داخل الأرشيف، ولن يتمكن File من قراءته. في هذه الحالة، من الأفضل دائماً استخدام التدفق (