كيفية قراءة وكتابة السلاسل النصية في الملفات النصية على Swift: نلقي نظرة تحت الغطاء
\n\nكل مطور، بغض النظر عن اللغة، يواجه عاجلاً أم آجلاً مهمة: read and write a String from text file. قد يبدو الأمر بسيطاً؟ لكن في Swift، مع نظام الأنواع الصارم والأمان، تتحول هذه العملية إلى رحلة مثيرة في عالم واصفات الملفات والترميزات ومديري الملفات. إذا كنت قد تساءلت يوماً: "ماذا يحدث حقاً عندما أستدعي write(to:) أو String(contentsOf:)؟" — فهذه المقالة لك.
لن نعرض فقط الحلول الجاهزة، بل سنحلل كل خطوة: من البحث عن الملف في بيئة الحماية (sandbox) إلى كتابة البايتات على القرص. استعدوا، سيكون ممتعاً!
\n\nلماذا لا يسمح Swift ببساطة بكتابة File.write(text)؟
\n\nعلى عكس Python أو JavaScript، حيث يمكنك فتح وكتابة ملف بسطر واحد، يتطلب Swift تحديداً صريحاً: بأي ترميز تكون السلسلة؟ أين يتم الحفظ (في Documents، Caches، Temp)؟ ماذا تفعل إذا لم يكن الملف موجوداً؟ هذا ليس خطأ، بل ميزة: هذا النهج يمنع تسرب البيانات ويضمن أنك تتحكم في كل مرحلة.
\n\nفي الأساس، هناك ثلاثة مكونات رئيسية:
\n- \n
- FileManager — "الموزع" الذي يعرف أين توجد جميع مجلدات تطبيقك. \n
- Data — البايتات الخام. يتعامل نظام الملفات معها مباشرة. \n
- String — تمثيلنا عالي المستوى، والذي يجب تحويله إلى Data والعكس. \n
عندما تكتب read and write a String from text file، يحدث تحت الغطاء سلسلة: String → Data (ترميز) → كتابة البايتات على القرص (عبر FileHandle أو طريقة Data).
مثال عملي: كتابة سلسلة نصية في ملف
\n\nلنبدأ بأبسط سيناريو وأكثرها فائدة. تخيل أنك تكتب تطبيق مذكرات وتريد حفظ نص الملاحظة.
\n\nimport Foundation\n\nlet textToSave = "مرحباً بالعالم! اليوم يوم رائع لتعلم Swift."\nlet fileName = "my_note.txt"\n\n// 1. الحصول على مسار مجلد Documents\nguard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {\n fatalError("فشل في الحصول على مجلد Documents")\n}\n\n// 2. إنشاء المسار الكامل للملف\nlet fileURL = documentsDirectory.appendingPathComponent(fileName)\n\n// 3. تحويل السلسلة إلى Data (بترميز UTF-8)\nguard let data = textToSave.data(using: .utf8) else {\n fatalError("خطأ في ترميز السلسلة")\n}\n\n// 4. كتابة البيانات على القرص\ndo {\n try data.write(to: fileURL, options: .atomic)\n print("تم حفظ الملف بنجاح في المسار: \\(fileURL.path)")\n} catch {\n print("خطأ في الكتابة: \\(error.localizedDescription)")\n}\n\nماذا يحدث هنا تحت الغطاء؟
\n- \n
FileManager.default.urls(for:in:)— يعيد URL المجلد. في iOS، هذه بيئة حماية (sandbox) معزولة. \n data(using: .utf8)— يتم ترميز كل حرف في السلسلة (حتى الرموز التعبيرية) إلى بايت واحد أو أكثر وفقاً لمعيار UTF-8. \n data.write(to:options:)— استدعاء نظامي يكتب البيانات بشكل ذري (إذا تم تحديد.atomic) إلى ملف مؤقت ثم يعيد تسميته إلى الملف الهدف. هذا يحمي من تلف البيانات في حالة الفشل. \n
قراءة سلسلة نصية من ملف: العملية العكسية
\n\nالآن، بعد أن حفظنا الملاحظة، دعنا نقرأها مرة أخرى. هذا مثال كلاسيكي على read and write a String from text file قيد التنفيذ.
\n\nimport Foundation\n\nlet fileName = "my_note.txt"\n\nguard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {\n fatalError("فشل في الحصول على مجلد Documents")\n}\n\nlet fileURL = documentsDirectory.appendingPathComponent(fileName)\n\ndo {\n // 1. قراءة البايتات الخام