اذهب إلى المحتوى

لوحة المتصدرين

  1. Ahmed Sadek Elamine Touahria

    • نقاط

      4

    • المساهمات

      510


  2. ملك S M Al

    ملك S M Al

    الأعضاء


    • نقاط

      3

    • المساهمات

      119


  3. Zeina Almakdisi

    Zeina Almakdisi

    الأعضاء


    • نقاط

      2

    • المساهمات

      168


  4. Monia Nagem

    Monia Nagem

    الأعضاء


    • نقاط

      2

    • المساهمات

      4


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 11/03/22 في كل الموقع

  1. مرحبا لقد رأيت العديد من التعليقات والمقالات هنا تتحدث عن githup ... لكنني لم افهم بعد ما هو هل هو بيئة عمل ام موقع ام ماذا؟ وبماذا سيفيدني كمبرمج مستقبلا؟ شكرا لكم
    2 نقاط
  2. @Zeina Makdisiالخطأ معناه أنه لم يتم التعرف على المتغير user مما يعني أن الشرط لم يتحقق ، وهذا كما أشار أخي @Kais Hasanفي الإجابة السابقة أن العبارة login(request,user) يجب أن تكون داخل الشرط if form.is_valid
    2 نقاط
  3. السلام عليكم مساء الخير كيف الحال حبيت أسالكم وش أفضل برنامج للتصميم
    1 نقطة
  4. عملت واجهة تسجيل دخول بدي اعمل كود يتحقق من اليوزر والباسوورد وينضافوا في ملف واذا كان تسجيل الدخول صحيح يحولوا على الويندوز الاخرى واحتاج مساعدة وشرح كيفف ممكن بدي اعملها
    1 نقطة
  5. ما هو الخطا #include <iostream> using namespace std; class list{ public: static int x; string str; }; int main() { list o1; list o2; o1.x=10; o2.x=20; o1.str="1111"; o2.str="nnn"; cout<<x; }
    1 نقطة
  6. المشكلة لما انفذ البرنامج يطلع الخطا في cout
    1 نقطة
  7. أنكب شاي ع اللاب وحصلت بعض المشاكل ومنها أن الكيبورد عند ضغط حرف يضغط لي حرف اخر م المشكله وكيف حلها ؟؟
    1 نقطة
  8. تم عرضه ويقول لا نستطيع اصلاحه بسبب شركته هل صعب اصلاح لابتوبات من شركة اي لايف ؟؟
    1 نقطة
  9. السلام عليكم ماهو. ال php output buffering وأود مقاله جيدة توضح عمل php mvc project
    1 نقطة
  10. أنا مبتدئة أريد مساعدة في كتابة كود بلغة الجافا كتابة برنامج جافا لممارسة الأعداد الأولية بين 0 و 99. • يُنشئ البرنامج عشوائيًا عددًا صحيحًا بين 0 و 99 مخزنًا حيث يعرض intNum سؤالًا يسأل المستخدم "هل الرقم ... رقم أولي؟ ". يجب على المستخدم الإجابة بـ "نعم" أو "لا". • بعد أن يكتب المستخدم الإجابة ، يعرض البرنامج رسالة توضح ما إذا كانت الإجابة صحيحة أم غير صحيحة.
    1 نقطة
  11. ولكن الا تعد github استضافة؟ لم أفهم هذا الجزء هل يجب رفعه عل استضافه اخري!
    1 نقطة
  12. مرحبا لدي قاعدة بيانات تحتوي على بيانات الاماكن( اسم المكان وخطوط الطول والعرض) احتاج الى استراد البيانات من قاعدة البيانات postgresql وعرضها على خرائط Google maps class Map(models.Model): Specialization = { ('Hospital','Hospital'), ('Clinic','Clinic'), ('Pharmacy','Pharmacy'), ('Health_Clinic','Health_Clinic'), } Name =models.CharField(_("Name:"),max_length=50) latitude =models.CharField(_("latitude:"),max_length=50) longitude =models.CharField(_("longitude:"),max_length=50) Specialization =models.CharField(_("Specialization:"), unique=True,choices=Specialization,max_length=100) <script> var request = { lat:{{Map.latitude}},////المشكلة انه لايتم استراد القيمة هنا lng:{{Map.longitude}}////المشكلة انه لايتم استراد القيمة هنا }; console.log(request) service = new google.maps.places.PlacesService(map); service.findPlaceFromQuery(request, (results, status) => { if (status === google.maps.places.PlacesServiceStatus.OK && results) { for (let i = 0; i < results.length; i++) { createMarker(results[i]); } map.setCenter(results[0].geometry.location); } }); } window.initMap = initMap; </script>
    1 نقطة
  13. مرحبا زينة، لربط البيانات من النموذج Map مع القالب يجب توفر دالة عرض view ورابط url. في الشفرة التي قمت بإرفاقها انت تقومين باستيراد النموذج Map مباشرة داخل القالب وهذا خطأ. يجب أولا عمل دالة عرض view تقوم باستخراج البيانات من قاعدة البيانات وارسالها إلى القالب. مثال بسيط: دالة العرض view: def get_maps(request): maps = Map.objects.all() return render(request, "maps.html", {maps: maps}) الرابط url: from views import get_maps # نقوم باستيراد الدالة get_maps urlpatterns = [ path('maps', get_maps, name='google_maps'), ] شفرة القالب تصبح على الشكل التالي: <script> var request = { lat:{{maps.0.latitude}}, lng:{{maps.0.longitude}} }; console.log(request) service = new google.maps.places.PlacesService(map); service.findPlaceFromQuery(request, (results, status) => { if (status === google.maps.places.PlacesServiceStatus.OK && results) { for (let i = 0; i < results.length; i++) { createMarker(results[i]); } map.setCenter(results[0].geometry.location); } }); } window.initMap = initMap; </script> تحياتي،
    1 نقطة
  14. يرجى إرفاق أي رسائل خطأ تظهر ضمن الطرفية console، وذكر لغة البرمجة وإطار العمل الذان يتم العمل بهما لتوضيح المشكلة
    1 نقطة
  15. طالما أن موقعك لا يحتوي على قاعدة بيانات فهذا قد لا يحتاج إلى حماية ، ﻷن الأصل هو حماية البيانات من الهجوم ووضع خطط لمثل هذه الحالات مثل backup وغيرها . فقط يمكنك رفع موقعك في استضافة githup الأشهر في مثل هذه المواقع وتربطها بالنطاق الخاص بك ، ﻷن خوادم شركة github التابعة ل microsoft مؤمنة وسريعة . أما إذا أصريت على حجز استضافة مدفوعة فهذه أبرز الخطوات لحماية موقعك اختر مزود استضافة أكثر أمانًا استعمال المصادقة الثنائية عند التسجيل في حسابك على احد مزودي خدمة الإستضافة إجعل كلمة السر قوية استخدم حماية DDoS فعل جدار الحماية السحابي Cloud Firewall
    1 نقطة
  16. كيف فيني ارفع الشكل الي لونه موف لانه مؤثر كتير عالتطبيق تبعي ..انا رسمت دائرة حول الشكل الي بدي ارفعه..لو سمحتو الي يعرف يبعت
    1 نقطة
  17. في هذا المثال ، نتلاشى في صورة عند التمرير بإضافة فئة fadeIn إليها عندما تدخل منفذ العرض. هذا هو js: const img = document.querySelector("img") const callback = (entries, observer) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("fadeIn") } }) } const options = {} const myObserver = new IntersectionObserver(callback, options) myObserver.observe(img) إنشاء مراقب التقاطع intersection observer أولاً ، نقوم بإنشاء مراقب تقاطع عن طريق استدعاء المُنشئ الخاص به وتمريره وظيفة callback وكائن خيارات اختياري. الخيارات كائن له 3 خصائص: const options = { root: null, rootMargin: '0px', threshold: 0 } root : افتراضي فارغ. إنه منفذ العرض. يمكن أن يكون المستند أو عنصر HTML. إذا كان الجذر فارغًا ، يتم تعيين المستند افتراضيًا. rootMargin: الافتراضي 0 بكسل. يحدد إزاحات كل جانب من المربع المحيط بالجذر. بمعنى آخر ، تقلل القيم الموجبة من المربع المحيط بالجذر وتزيده القيم السالبة. حاول تمرير المربعات الثلاثة في هذا المثال. callback const callback = (entries, observer) => { entries.forEach(entry => { // يصف كل إدخال تغييرًا في التقاطع لواحد تمت ملاحظته // العنصر الهدف: // entry.boundingClientRect // entry.intersectionRatio // entry.intersectionRect // entry.isIntersecting // entry.rootBounds // entry.target // entry.time }); }; لقد استخدمتهما في تحريك fadeIn: const callback = (entries, observer) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("fadeIn") } }) } لتحديد عنصر مراد مراقبته ، نستخدم دالة observe() الخاصة بمراقب التقاطع. إذا كنت تريد ملاحظة العديد من العناصر ، فعليك إضافتها واحدة تلو الأخرى. myObserver.observe(img1) myObserver.observe(img2) myObserver.observe(img3) //----- أو const imgList = document.querySelectorAll(".imgToAnimate") imgList.forEach(img => { myObserver.observe(img) }) ﻹيقافها myObserver.unobserve(img) // ----- أو const callback = (entries, observer) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("fadeIn") observer.unobserve(entry.target) // دالة إيقاف } }) } وهذا مثال <!------------------HTML---------------> <div class="container"> <div class="wrapper"> <img class="imgA" src="https://ljc-dev.github.io/hosted-assets/thumb-a.png" alt="avatar a"> </div> <div class="wrapper"> <img class="imgB" src="https://ljc-dev.github.io/hosted-assets/thumb-b.png" alt="avatar b"> </div> <div class="wrapper"> <img class="imgC" src="https://ljc-dev.github.io/hosted-assets/thumb-c.png" alt="avatar c"> </div> <div class="wrapper"> <img class="imgD" src="https://ljc-dev.github.io/hosted-assets/thumb-d.png" alt="avatar d"> </div> </div> * { margin: 0; padding: 0; box-sizing: border-box; } html, body { width: 100%; } html { scroll-behavior: smooth; } .container { width: 100%; height: 100vh; overflow-x: hidden; overflow-y: auto; padding-top: 12rem; } .wrapper { position: relative; margin: 5rem auto; width: 400px; height: 400px; } img { position: absolute; top: 0; left: 0; height: 400px; opacity: 0; width: 400px; transition: all 1s; } .imgA { transform: translateX(-200px); opacity: 0; } .imgB { transform: translateX(200px); opacity: 0; } .imgC { transform: translateY(200px); opacity: 0; } .imgD { transform: scale(0); } .fadeInLeft { transform: translateX(0px); opacity: 1; } .fadeInRight { transform: translateX(0px); opacity: 1; } .fadeInBtm { transform: translateY(0px); opacity: 1; } .zoomIn { transform: scale(1); opacity: 1; } const container = document.querySelector(".container") const wrappers = document.querySelectorAll(".wrapper") const imgs = document.querySelectorAll("img") const animClasses = [ "fadeInLeft", "fadeInRight", "fadeInBtm", "zoomIn", ] const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { const currentIndex = Array.from(wrappers).indexOf(entry.target) if (entry.isIntersecting) { imgs[currentIndex].classList.add(animClasses[currentIndex]) } else { if (entry.boundingClientRect.y > 0) { imgs[currentIndex].classList.remove(animClasses[currentIndex]) } } }) }, { root: container, threshold: 0.1, }) wrappers.forEach(wrapper => { observer.observe(wrapper) })
    1 نقطة
  18. نعم يمكنك رؤية الأكواد البرمجية لأي مشروع منشور على GitHub دون تنزيله ، من هنا يمكنك الإنتقال إلى أحد المشاريع التي تم شرحها في الدورات يمكنك أن ترى الأكواد البرمجية دون تنزيل الملف . كما تعلم أن شروط التقديم اللإمتحان كتالي :- اتمام اربعة مسارات تعليمية على الاقل من الدورة المشترك بها . ارسال المشاريع العملية المطبقة خلال المسارات. رفع هاته المشاريع على حسابك في GitHub. يمكنك إنجاز أربع مسارات وتقديم الإمتحان وبعد الإمتحان والنجاح به يمكنك العودة واكمال باقي المسارات . أيضاً الممارسة والتطبيق المستمر لما تعلمته في الدورة سوف يجعلك تستذكر المعلومات ولن تنساها ولن تواجه مشكلة في وقت تقديم الإمتحان . لإطلاع أكثر حول الامتحان من هنا بحيث يوجد تفاصيل أكثر حول الإمتحان .
    1 نقطة
  19. if form.is_valid(): form.save() username = form.cleaned_date.get('username') password = form.cleaned_date.get('password') user = authenticate(username=username , password=password) login(request,user) هنا في السطر الأخير، في حال لم يتنفذ ما بداخل ال if فهذا سيؤدي لخطأ حيث أن ال user غير معرف، أعتقد أنها يجب أن تكون بداخل ال if.
    1 نقطة
  20. إن الجواب على سؤالك الأول هو نعم في حال كان قصدك أنك تريد رؤية الكود، و لكن في حال أردت تشغيل الكود و لم يكن صاحب المشروع قد قام برفعه على استضافة فالإجابة لا. من أجل السؤال الثاني، إن المطلوب هو أنك تفهم ما الذي يتم عمله، في حال كنت تفهم الآلية العامة فهذا جيد جداً، حيث يمكنك ببساطة أن تعود إلى ما نسيته و تحضر الدرس مرة أخرى، هذا سيساعدك، أي تأكد أنك أصبحت ملم بكل جوانب الدورة و عندها يمكنك التقدم للاختبار و أنت واثق من نفسك و من معلوماتك.
    1 نقطة
  21. ظل البيانات والبرامج المُخزَّنة بذاكرة الحاسوب الرئيسية main memory متوفرةً طوال فترة تشغيله، ولكن يجب الاستعانة بالملفات للإبقاء عليها بصورة دائمة؛ حيث تمثِّل مجموعةً من البيانات المُخزَّنة بقرصٍ صلب hard disk، أو بشريحة ذاكرة USB، أو بقرصٍ مضغوط CD-ROM، أو بأي نوعٍ آخر من أجهزة التخزين. تُنظَّم الملفات داخل مجلدات، وبإمكان كل مجلدٍ أن يحتوي على مجلداتٍ أخرى إلى جانب الملفات، كما يَملُك كل مجلدٍ وملف اسمًا يُعرِّف هويته. تستطيع البرامج عمومًا قراءة البيانات من ملفاتٍ موجودة، وكذلك إنشاء ملفاتٍ جديدة وكتابة البيانات بها، وتعتمد جافا على مجاري تدفق streams الدْخل والخرج لفعل ذلك؛ حيث تُستخدَم الكائنات المنتمية للصنف FileReader -وهو صنفٌ فرعيٌ من الصنف Reader- لقراءة البيانات المحرفية المهيأة للقراءة human-readable من ملفٍ معين؛ وتُستخدَم بالمثل الكائنات المنتمية للصنف FileWriter -وهو صنفٌ فرعيٌ من الصنف Writer- لكتابة البيانات المهيأة للقراءة بملف. يُستخدَم الصنفان FileInputStream و FileOutputStream للتعامل مع الملفات التي تُخزِّن البيانات بصيغةٍ مهيأة للآلة. سنناقش خلال هذا المقال الأصناف التي تتعامل مع الملفات بالصيغة المحرفية فقط، أي الصنفين FileReader و FileWriter، ولكن تذكَّر أن الصنفين FileInputStream و FileOutputStream يُستخدمان في العموم بنفس الطريقة. لاحِظ أن كلَّ تلك الأصناف مُعرَّفةٌ في حزمة java.io. قراءة الملفات والكتابة بها يستقبل باني constructor الصنف FileReader اسم ملف معين مثل معاملٍ parameter، ويُنشِئ مجرى stream مُدْخَلات لقراءة محتويات ذلك الملف؛ فإذا لم يَكُن الملف المُخصَّص موجودًا، فسيُبلِّغ الباني عن استثناء exception من النوع FileNotFoundException. بفرض لدينا ملفٌ اسمه "data.txt"، ونريد قراءة البيانات الموجودة به، يُمكِننا إذًا إنشاء مجرى مُدْخَلات لذلك الملف بكتابة ما يلي: FileReader data; // 1 try { data = new FileReader("data.txt"); // أنشِئ المجرى } catch (FileNotFoundException e) { ... // عالج الخطأ المُحتمَل } حيث تعني [1]: صرِّح عن المُتغيّر قبل تعليمة try؛ وإلا سيُصبِح محليًا ضمن كتلة try، ولن تتمكَّن من اِستخدَامه بالبرنامج لاحقًا. يُمكِننا في الواقع ضبط تعليمة try...catch بالأعلى، بحيث تلتقط استثناءات الصنف IOException؛ لأن الصنف FileNotFoundException هو بالنهاية صنفٌ فرعيٌ subclass من الصنف IOException، ويُمكِننا في العموم التقاط أي خطأٍ يحدث أثناء عمليات الدخل والخرج باستخدام عبارة catch خُصِّصت لمعالجة الاستثناءات من النوع IOException. يُمكِننا أن نبدأ بقراءة البيانات من كائنات الصنف FileReader بمجرد إنشائها، ولكن نظرًا لعدم تضمُّنها سوى بعض التوابع البسيطة، فسنضطّر عادةً إلى تغليفها ضمن كائنٍ من النوع Scanner أو النوع BufferedReader أو أي صنفٍ مُغلِّف آخر. انظر المقال السابق لمزيدٍ من المعلومات عن الصنفين BufferedReader و Scanner. تُنشِئ الشيفرة التالية كائنًا من النوع BufferedReader لقراءة بيانات ملفٍ اسمه "data.dat": BufferedReader data; try { data = new BufferedReader( new FileReader("data.dat") ); } catch (FileNotFoundException e) { ... // عالج الاستثناء } يُسهِل تغليف كائنات الصنف Reader بكائناتٍ تنتمي للصنف BufferedReader من قراءة أسطر الملفات، كما تُعزِّز خاصية التخزين المؤقت buffering من كفاءتها. يُمكِننا بنفس الكيفية إنشاء كائنٍ من الصنف Scanner لقراءة بيانات ملفٍ معين، مع أننا نلجأ عادةً في مثل تلك الحالات إلى إنشاء كائنٍ من النوع File مباشرةً (سنناقش ذلك بالأسفل): Scanner in; try { in = new Scanner( new File("data.dat") ); } catch (FileNotFoundException e) { ... // عالِج الاستثناء } ينطبق الأمر نفسه على ملفات الخرج؛ حيث ينبغي في تلك الحالة إنشاء كائنٍ من النوع FileWriter، والذي نلجأ عادةً إلى تغليفه ضمن كائنٍ من النوع PrintWriter. قد يُبلِّغ باني الصنف FileWriter عن استثناء من النوع IOException؛ ولهذا ينبغي أن نحيطه بتعليمة try..catch. لنفترض مثلًا أننا نريد كتابة بياناتٍ معينة بملفٍ اسمه "result.dat"، يُمكِننا أن نَستخدِم الشيفرة التالية: PrintWriter result; try { result = new PrintWriter(new FileWriter("result.dat")); } catch (IOException e) { ... // عالِج الاستثناء } كما هو الحال مع الصنف Scanner، نُمرِّر عادةً في تلك الحالات معاملًا من النوع File لباني الصنف PrintWriter، ويؤدي ذلك إلى تغليف كائن الصنف File تلقائيًا ضمن كائنٍ ينتمي للصنف FileWriter، ثم يُنشِئ الحاسوب بعدها كائنًا من الصنف PrintWriter. انظر الشيفرة التالية: PrintWriter result; try { result = new PrintWriter(new File("result.dat")); } catch (IOException e) { ... // عالِج الاستثناء } بإمكاننا أيضًا أن نُمرِّر للباني سلسلةً نصيةً من النوع String، ويَعُدُّها الباني في تلك الحالة اسمًا لملف؛ بينما لو مرَّرنا سلسلةً نصيةً من النوع String إلى باني الصنف Scanner، فإنه لا يَعُدّها اسمًا لملف، وإنما يقرأ محارف السلسلة النصية ذاتها. في حالة عدم وجود ملفٍ اسمه "result.dat"، يُنشَئ ملفٌ جديدٌ بنفس الاسم؛ أما إذا كان موجودًا بالفعل، تَحِلّ البيانات التي يُفترض من البرنامج كتابتها بالملف محلّ محتوياته الحالية. لاحِظ أنك لن تتلقَّ أي تحذيرٍ بشأن ذلك. إذا أردت تجنُّب حدوث ذلك، عليك أن تفحص أولًا فيما إذا كان هناك ملفٌ بنفس الاسم قبل إنشاء مجرًى له كما سنناقش لاحقًا. قد يُبلِّغ باني الصنف PrintWriter عن استثناء من النوع IOException، إذا حاولت إنشاء ملفٍ داخل قرصٍ غير مسموحٍ بالكتابة به، أي لا يُمكِن تعديله. عندما تُنهِي عملك مع كائن من الصنف PrintWriter، يجب أن تستدعِي تابعه flush()‎ بكتابة شيءٍ مثل result.flush()‎؛ وذلك حتى تتأكَّد من إرسال الخرج بالكامل إلى مقصده؛ وإذا نسيت أن تَستدعِيه، قد لا يظهر بالملف بعض البيانات التي أرسلتها إليه. بعد أن تُنهِي تعاملك مع ملفٍ معين، يُفضَّل أن تغلقه؛ بمعنى أن تُبلِّغ نظام التشغيل أنك انتهيت من اِستخدَامه. يُمكِنك أن تَستدعِي التابع close()‎ المُعرَّف بالصنف PrintWriter، أو BufferedReader، أو Scanner حتى تغلق الملف. بمجرد إغلاق ملفٍ معين، لا يُمكِنك أن تقرأ بياناته، أو أن تُرسِل إليه أية بيانات، إلا إذا أعدت فتحه مرةً أخرى بإنشاء مجرًى جديد. قد يُبلِّغ التابع close()‎ بغالبية أصناف المجاري -بما في ذلك الصنف BufferedReader- عن حدوث استثنناء من النوع IOException، والذي لا بُدّ من معالجته. يُعيد لحسن الحظ الصنفان PrintWriter و Scanner تعريف override ذلك التابع لمنعه من التبليغ عن مثل تلك الاستثناءات. إذا نسيت إغلاق ملفٍ معين، فإنه يُغلَق أوتوماتيكيًا بعد انتهاء البرنامج أو قد يُغلّق قبل ذلك بواسطة كانس المهملات garbage collection، ولكن لا يُفضَّل الاعتماد على ذلك. يقرأ البرنامج التالي أعدادًا من ملفٍ اسمه "data.dat"، ثم يعيد كتابة نفس تلك الأعداد، ولكن بترتيبٍ معاكس إلى ملفٍ آخر اسمه "result.dat". (ملاحظة: يَفترِض البرنامج احتواء الملف "data.dat" على أعدادٍ حقيقية فقط). يَستخدِم هذا البرنامج الصنف Scanner لقراءة ملف الدْخَل، كما يعتمد على معالجة الاستثناءات لفحص المشكلات المحتملة. قد لا يكون البرنامج التالي مفيدًا تمامًا، ولكنه يُظهِر على الأقل أساسيات التعامل مع الملفات بوضوح: import java.io.*; import java.util.ArrayList; import java.util.Scanner; // 1 public class ReverseFileWithScanner { public static void main(String[] args) { Scanner data; // لقراءة البيانات PrintWriter result; // مجرى محارف خرج لإرسال البيانات ArrayList<Double> numbers; // قائمة لحمل البيانات numbers = new ArrayList<Double>(); try { // أنشئ مجرى دخل data = new Scanner(new File("data.dat")); } catch (FileNotFoundException e) { System.out.println("Can't find file data.dat!"); return; // أنهِ البرنامج بالعودة من البرنامج } try { // أنشِئ مجرى خرج result = new PrintWriter("result.dat"); } catch (FileNotFoundException e) { System.out.println("Can't open file result.dat!"); System.out.println("Error: " + e); data.close(); // أغلق الملف return; // أنهِ البرنامج } while ( data.hasNextDouble() ) { // اقرأ الملف حتى نهايته double inputNumber = data.nextDouble(); numbers.add( inputNumber ); } // اطبع الأعداد بترتيبٍ معكوس for (int i = numbers.size()-1; i >= 0; i--) result.println(numbers.get(i)); System.out.println("Done!"); data.close(); result.close(); } // end of main() } // end class ReverseFileWithScanner حيث أن [1] يقرأ البرنامج الأعداد من ملفٍ اسمه "data.dat"، ثم يكتبها إلى ملفٍ اسمه "result.dat" بترتيبٍ معكوس. لا بُدّ أن يحتوي الملف المُدْخَل على أعدادٍ حقيقيةٍ فقط. يتوقف البرنامج السابق عن قراءة بيانات الملف بمجرد قراءته لمُدْخَلٍ غير عددي، ولا يَعُدّه خطأً. كما ذكرنا بنهاية مقال الاستثناءات exceptions وتعليمة try..catch في جافا، يَشيع نمط إنشاء "موردٍ resource" معينٍ أو فتحه، ثم اِستخدَامه، وغلقه، وهو نمطٌ مدعومٌ من قِبَل تعليمة try..catch. بحسب هذا السياق، تُعدّ الملفات بمثابة مواردٍ مثلها مثل أصناف Scanner و PrintWriter وغيرها من مجاري جافا للدْخَل والخرج. تُعرِّف جميع تلك الموارد التابع close()‎، ويُفضَّل طبعًا إغلاقها بعد الانتهاء من اِستخدَامها. نظرًا لأن تلك الأصناف تُنفِّذ الواجهة AutoCloseable، تُعدُّ جميعها مواردًا بحسب تعليمة try..catch، ولهذا يُمكِننا إذًا أن نَستخدِم تلك التعليمة لإغلاق الموارد أوتوماتيكيًا بمجرد انتهاء تنفيذ التعليمة دون الحاجة إلى إغلاقها يدويًا ضمن تعليمة finally، وذلك بفرض أنك فتحت المورد واِستخدَمته ضمن نفس تعليمة try..catch. يُعدّ البرنامج التوضيحي ReverseFileWithResources.java نسخةً أخرى من المثال الذي تعرَّضنا له بالأعلى، حيث يَستخدِم البرنامج تعليمات try..catch لقراءة البيانات من ملف، وكتابتها إلى ملفٍ آخر. كنا قد فتحنا الملف ضمن تعليمة try، واِستخدَمناه ضمن تعليمة try أخرى بالنسخة الأصلية من البرنامج. يتطلّب في المقابل نمط المورد حدوث الخطوتين ضمن تعليمة try واحدة، ولهذا علينا إعادة ترتيب الشيفرة، وهو ما قد يُصعِّب معرفة مصدر الاستثناء. تتضمَّن الشيفرة التالية تعليمة try..catch واحدةً مسؤولةً عن فتح ملف المُدْخَلات وقرائته وغلقه أتوماتيكيًا: try( Scanner data = new Scanner(new File("data.dat")) ) { // اقرأ الأعداد وأضِفها إلى المصفوفة while ( data.hasNextDouble() ) { // اقرأ حتى تصل إلى نهايته double inputNumber = data.nextDouble(); numbers.add( inputNumber ); } } catch (FileNotFoundException e) { // قد يحدث إذا لم يكن الملف موجودًا أو لا يُمكِن قراءته System.out.println("Can't open input file data.dat!"); System.out.println("Error: " + e); return; // عند حدوث خطأmain() العودة من } يُنشِئ السطر الأول المورد data. تتضمَّن قواعد الصيغة syntax لتعليمة try التصريح عن المورد وإعطائه قيمةً مبدئية داخل أقواسٍ بعد كلمة try. يُمكِننا أن نُصرِّح عن عدة مواردٍ يَفصِل بينها فاصلةٌ منقوطة، وتُغلَق جميعها بترتيبٍ معاكسٍ لترتيب التصريح عنها. الملفات والمجلدات هناك بعض الجوانب الأخرى المُتعلِّقة بأسماء الملفات، والتي لم نذكرها حتى الآن. بدايةً، إذا أردنا أن نُشير إلى ملفٍ مُحدَّد بوضوح، فلا بُدّ أن نوفِّر معلوماتٍ كافيةً عن كُلٍ من اسم الملف واسم المجلد الواقع به؛ لأنك إذا استخدمت اسم ملفٍ بسيطٍ، مثل "data.dat"، أو "result.dat"، فسيَفترِض الحاسوب وجود ذلك الملف بمجلدٍ يُعرَف باسم "المجلد الحالي current directory أو المجلد الافتراضي أو مجلد العمل"، والذي لا يُمثِل مكانًا ثابتًا، فقد يُغيِّره المُستخدِم أو حتى البرنامج. ولهذا، إذا أردت أن تُشير إلى ملفٍ معين، وكان ذلك الملف موجودًا بمجلدٍ غير المجلد الحالي، فيجب أن تشير إليه بواسطة مساره؛ أي بتوفير معلوماتٍ عن كُلٍ من اسم الملف، واسم المجلد الواقع به الملف. يتوفَّر نوعان من أسماء المسارات، وهو ما قد يُعقِّد الأمور قليلًا، وهما: أسماء مطلقة للمسارات absolute path names، وأسماء نسبية للمسارات relative path names؛ حيث يُحدِّد الاسم المطلق للمسار اسم ملفٍ واحدٍ فقط من بين جميع الملفات المُتاحة بالحاسوب بوضوح، بسبب احتواء اسم المسار في تلك الحالة على كافة المعلومات المُتعلِّقة باسم الملف وبالمجلد المُتضمِّن له؛ بينما يُوضِّح الاسم النسبي للمسار الكيفية التي يستطيع الحاسوب بها العثور على الملف بدءًا من المجلد الحالي. تختلف مع الأسف قواعد صيغة كُلٍ من أسماء الملفات والمسارات من حاسوبٍ إلى آخر إلى حدٍ ما. ألقِ نظرةً على بعض الأمثلة على ذلك: data.dat: يُمثِّل ملفًا اسمه "data.dat" مع فرض وجوده بالمجلد الحالي. ينطبق ذلك على أي حاسوب. ‎/home/eck/java/examples/data.dat: يُمثِّل الاسم المطلق لمسارٍ معين بأنظمة تشغيل UNIX، بما في ذلك Linux و Mac OS X، ويُشير إلى ملفٍ اسمه "data.dat"، موجودٍ بمجلدٍ اسمه "examples"، موجودٍ بدوره بمجلدٍ اسمه "java"، وهكذا. ‎C:\eck\java\examples\data.dat: يُمثِّل الاسم المطلق لمسارٍ معيّن بأنظمة تشغيل Windows. examples/data.dat: يُمثِّل الاسم النسبي لمسارٍ معيّن بأنظمة تشغيل UNIX، حيث يُمثِّل "examples" اسم مجلدٍ يُفترَض وجوده بالمجلد الحالي؛ أما "data.dat" فهو اسم ملفٍ موجودٍ ضمن المجلد "examples". الاسم النسبي المكافئ لذلك المسار بأنظمة تشغيل Windows هو "examples\data.dat". ‎../examples/data.dat: يُمثِّل الاسم النسبي لمسارٍ معيّنٍ بأنظمة تشغيل UNIX، ويَعنِي ما يلي: اذهب إلى المجلد المُتضمِّن للمجلد الحالي.، حيث ستَجِد هناك مجلدًا اسمه "examples"، اذهب إليه وستعثُر على ملفٍ اسمه "data.dat". تعني ".." عُدّ مجلدًا واحدًا للوراء. يُمثِّل "‎..\examples\data.dat" نفس المسار بأنظمة Windows. إذا كنت تتعامل مع الملفات من خلال برنامج سطر أوامر، وكانت أسماء الملفات بسيطةً نوعًا ما، ومُخزَّنة أيضًا بنفس مجلد البرنامج، فقد تسير الأمور على ما يرام. سنرى لاحقًا في هذا المقال طريقةً أفضل تَسمَح للمُستخدِم باختيار الملفات من خلال برنامج واجهة مُستخدِم رسومية، وهو ما يساعد على تجنُّب مشكلات أسماء المسارات تمامًا. تستطيع برامج جافا الإشارة إلى الاسم المطلق لمساري مجلدين مهمين، هما المجلد الحالي والمجلد الرئيسي للمُستخدِم؛ حيث تُعدّ أسماء تلك المجلدات خاصياتٍ بالنظام، ويُمكِن قراءتها باستدعاء الدوال التالية: System.getProperty("user.dir")‎: تعيد قيمةً من النوع String تُمثِّل الاسم المطلق لمسار المجلد الحالي. System.getProperty("user.home")‎: تعيد قيمةً من النوع String تُمثِّل الاسم المطلق لمسار المجلد الرئيسي للمُستخدِم. تُوفِّر جافا الصنف java.io.File، والذي يُجنِّبنا لحسن الحظ كثيرًا من المشكلات المتعلّقة بالاختلافات بين أسماء المسارات بالمنصات المختلفة. لا يُمثِّل الكائن المنتمي لهذا الصنف أي ملفٍ تمثيلًا فعليًا، وإنما يُمثِّل "اسم الملف"، ومن الممكن أن يكون الملف الذي يُشير إليه الاسم موجودًا أو غير موجود. ينطبِق الأمر ذاته على المجلدات؛ أي يُمكِن لكائنٍ من النوع File أن يُمثِّل مجلدًا معينًا بنفس الكيفية التي يُمكِنه بها أن يُمثِّل ملفًا. يَستقبِل الباني new File(String)‎ المُعرَّف بطبيعة الحال بالصنف File اسمًا لمسارٍ معين، ويُنشِئ كائنًا من النوع File يُشير إلى الملف الموجود بذلك المسار. يُمكِن لاسم المسار المُمرَّر أن يكون بسيطًا أو نسبيًا أو مُطلقًا. على سبيل المثال، يُنشِئ الباني new File("data.dat")‎ كائنًا من النوع File يُشير إلى ملفٍ اسمه "data.dat" بالمجلد الحالي. يتوفَّر باني آخر هو new File(File,String)‎، والذي يَستقبِل مُعاملين: الأول هو كائنٌ من النوع File يُشير إلى مجلدٍ معين، أما الثاني فيُمكِنه أن يكون اسمًا لملفٍ موجودٍ ضمن المجلد المُخصَّص، أو مسارًا نسبيًا من ذاك المجلد إلى الملف المطلوب. تتضمَّن كائنات الصنف File توابع نسخ instance methods مفيدة. بفرض أن file هو مُتغيّرٌ من النوع File، يُمكِننا أن نَستخدِم أيًا من التوابع التالية: file.exists()‎: يُعيد القيمة المنطقية true إذا كان الملف الذي يُخصِّصه الكائن file موجودًا. اِستخدِم هذا التابع إذا أردت تجنُّب كتابة بياناتك بينما تُنشِئ مجرى خرجٍ جديد على ملفٍ موجودٍ مُسبقًا. تعيد الدالة file.canRead()‎ القيمة true إذا كان الملف موجودًا وكان البرنامج يَملُك صلاحيةً لقرائته؛ بينما تعيد الدالة file.canWrite()‎ القيمة true إذا كان البرنامج يَملُك صلاحيةً للكتابة بذلك الملف. file.isDirectory()‎: يُعيد القيمة المنطقية true إذا كان file يشير إلى مجلدٍ ما؛ بينما يعيد القيمة false إذا كان الكائن يشير إلى ملفٍ سواءً كان ذلك الملف موجودًا أم لا. file.delete()‎: يحذِف الملف إذا كان موجودًا، ويعيد قيمةً منطقيةً للدلالة على نجاح عملية الحذف أو فشلها. file.list()‎: إذا كان file يشير إلى مجلد، فستُعيد الدالة مصفوفةً من النوع String[]‎ تحتوي على أسماء الملفات الموجودة بذلك المجلد؛ أما إذا لم يَكن كذلك، فستُعيد القيمة الفارغة null. يعمل التابع file.listFiles()‎ بنفس الطريقة باستثناء أنه يعيد مصفوفةً عناصرها من النوع File وليس String. يُنشِئ البرنامج التالي قائمةً بأسماء جميع الملفات الموجودة بمجلدٍ معين يُخصِّصه المُستخدِم. لاحِظ أننا اِستخدَمنا الصنف Scanner من أجل قراءة مُدخَلات المُستخدِم: import java.io.File; import java.util.Scanner; // 1 public class DirectoryList { public static void main(String[] args) { String directoryName; // اسم المجلد الذي أدخله المُستخدِم File directory; // كائنٌ يشير إلى المجلد String[] files; // مصفوفة بأسماء الملفات الموجودة بالمجلد Scanner scanner; // لقراءة سطرٍ مُدْخل واحد أدخله المُستخدِم scanner = new Scanner(System.in); // للقراءة من الدخل القياسي System.out.print("Enter a directory name: "); directoryName = scanner.nextLine().trim(); directory = new File(directoryName); if (directory.isDirectory() == false) { if (directory.exists() == false) System.out.println("There is no such directory!"); else System.out.println("That file is not a directory."); } else { files = directory.list(); System.out.println("Files in directory \"" + directory + "\":"); for (int i = 0; i < files.length; i++) System.out.println(" " + files[i]); } } // end main() } // end class DirectoryList حيث تعني [1]: يَعرِض هذا البرنامج قائمةً بالملفات الموجودة بالمجلد الذي خَصَّصه المُستخدِم. يطلب البرنامج من المُستخدِم كتابة اسم المجلد، فإذا لم يكن الاسم المُدْخَل مجلدًا، يطبع البرنامج رسالةً ويُغلق. تتضمَّن جميع الأصناف المُستخدَمة للقراءة من الملفات والكتابة بها بُناة constructors كائن، حيث تَستقبِل تلك البُناة كائنًا من النوع File مثل معاملٍ. على سبيل المثال، إذا كان file متغيرًا من النوع File، وكنت تريد قراءة محارف من ذلك الملف، يُمكِنك إنشاء كائنٍ من النوع FileReader بكتابة new FileReader(file)‎. صناديق نوافذ التعامل مع الملفات تحتاج الكثير من البرامج إلى طريقةٍ تَسمَح بها للمُستخدِم باختيار ملفٍ معين، بحيث يُمكِنها بعد ذلك استخدام الملف المُخصَّص أثناء عمليات الدخل والخرج. إذا سَمحَنا للمُستخدِم بكتابة اسم الملف يدويًا، فإننا بذلك نفترض فهمه لطريقة عمل الملفات والمجلدات. في المقابل، إذا دعَّمنا البرنامج بواجهة مُستخدمٍ رسومية، فإننا سنُمكِّن المُستخدِم من اختيار الملف من خلال صندوق نافذة ملف file dialog box؛ حيث يُعدُّ هذا الصندوق نافذةً يستطيع البرنامج أن يفتحها إذا أراد أن يَسمَح للمُستخدِم باختيار ملفٍ معينٍ للدخل أو للخرج. توفِّر مكتبة جافا إف إكس JavaFX الصنف FileChooser ضمن حزمة javafx.stage، والذي يُمكِنه عرض صندوق نافذة للتعامل مع الملفات، وذلك بصورةٍ مُستقلة عن المنصة التي يَعمَل عليها البرنامج. يَعرِض صندوق نافذة فتح ملف للمُستخدِم قائمةً بالملفات والمجلدات الفرعية الموجودة ضمن مجلدٍ معين، مما يَسمَح له بأن يختار بسهولةٍ ملفًا معينًا ضمن ذلك المجلد، كما تُمكِّنه من التنقل بين المجلدات. لا يستقبل باني الصنف FileChooser أية معاملات. لاحِظ أن صندوق النافذة لا يظهر تلقائيًا على الشاشة بمجرد إنشاء كائنٍ من النوع FileChooser، وإنما ينبغي استدعاء تابعٍ مُعرَّفٍ بهذا الكائن لإظهار صندوق النافذة. ستَستدعِي عادةً بعض توابع النسخ الأخرى المُعرَّفة بالكائن، والخاصة بضَبْط بعض خاصيات صندوق النافذة قبل أن تَعرِضها، حيث يمكن مثلًا تخصيص قيمةٍ افتراضيةٍ مثل اسم للملف. قد يكون لصندوق النافذة "مالك owner" يمثّل نافذةً، أي كائنًا من النوع Stage بمكتبة جافا إف إكس JavaFX. لا يَستطيع المُستخدِم أن يتفاعل مع النافذة المالكة حتى يُنهِي تعامله مع صندوق النافذة المفتوح؛ إما بغلقه؛ أو باختيار ملف. يُمكِننا أن نُخصِّص مالك صندوق نافذةٍ معينة بتمريره معاملًا للتابع المسؤول عن عرض صندوق النافذة؛ كما يُمكِن للمالك أن يكون فارغًا، وعندها لا يتوقف تفاعل المُستخدِم مع أي نوافذ أثناء عرض صندوق النافذة. هناك نوعان من صناديق نوافذ الملفات: صندوق نافذة فتح ملف وصندوق نافذة حفظ ملف؛ حيث يَسمَح الأول للمُستخدِم بتخصيص إحدى الملفات الموجودة مُسبقًا لفتحها وقراءتها بالبرنامج؛ أما الثاني فيَسمَح للمُستخدِم بتخصيص ملفٍ قد يكون موجودًا أو لا لكتابة بعض البيانات به. يُعرِّف الصنف FileChooser تابعي نسخة لعرض أيٍّ من الصندوقين على الشاشة. إذا كان fileDialog مُتغيرًا من النوع FileChooser، فإنه يُوفِّر التوابع التالية: fileDialog.showOpenDialog(window)‎: يَعرِض صندوق نافذة فتح ملف على الشاشة، حيث يَستقبِل مُعاملًا يُمثِّل مالك صندوق النافذة المُفترَض فتحها. لا يعيد التابع أي قيمةٍ حتى يختار المُستخدِم ملفًا أو يَغلِق النافذة بدون اختيار أي ملف؛ حيث يعيد التابع في الحالة الأولى قيمةً من النوع File تُمثِّل الملف الذي اختاره المُستخدِم؛ بينما يُعيد في الحالة الثانية القيمة الفارغة null. fileDialog.showSaveDialog(window)‎: يَعرِض صندوق نافذة حفظ ملف، مالكها هو المعامل window. يعمل كلٌ من معامل التابع والقيمة المعادة منه بنفس أسلوب التابع showOpenDialog()‎؛ فإذا اختار المُستخدِم ملفًا موجودًا بالفعل، فسيسأله النظام أوتوماتيكيًا فيما إذا كان يريد بالفعل استبدال ذلك الملف، ويُمكِنك في تلك الحالة تخزين البيانات بالملف المُخصَّص دون القلق بشأن أي خطأٍ غير متوقَّع. fileDialog.setTitle(title)‎: يَستقبِل التابع سلسلةً نصيةً مثل معاملٍ لتخصيص عنوانٍ يَظهَر بشريط عنوان صندوق النافذة. ينبغي أن تَستدعِي هذا التابع قبل عرض صندوق النافذة. fileDialog.setInitialFileName(name)‎: يَضبُط اسمًا افتراضيًا يظهر بصندوق مُدْخَلات اسم الملف. لاحِظ أن المعامل هو سلسلةٌ نصية؛ فإذا كانت القيمة المُمرَّرة للمعامل فارغة، فإن صندوق الإدخال يكون بدوره فارغًا. ينبغي استدعاء هذا التابع قبل عرض صندوق النافذة المعنيّة. fileDialog.setInitialDirectory(directory)‎: يََضبُط أي مجلدٍ ينبغي عرضه مبدئيًا عند فتح صندوق نافذة فتح الملف. لاحِظ أن المعامل الذي يَستقبِله التابع يَكون من النوع File؛ فإذا كانت القيمة المُمرَّرة للمعامل فارغة، يعتمد المجلد المبدئي على الإعدادات الافتراضية للنظام (قد يكون المجلد الذي شَغلّت البرنامج منه)؛ أما إذا لم تَكن القيمة المُمرَّرة فارغة، فلا بُدّ أن تكون كائنًا من النوع File يُمثِّل مجلدًا لا ملفًا، وإلا سيقع خطأ. ينبغي استدعاء هذا التابع قبل عرض صندوق النافذة المعنيّة. يتضمَّن أي برنامجٍ نموذجي يتعامل مع الملفات الأمرين "افتح" و "احفظ"؛ فعندما يختار المُستخدِم ملفًا معينًا لفتحه أو لحفظ البيانات به، يُمكِننا أن نُخزِّن كائن الصنف File الذي يُمثِّل الملف الذي اختاره المُستخدِم بمتغير نسخة instance variable، بحيث نَستخدِمه بعد ذلك لضبط المجلد المعروض مبدئيًا، أو حتى لضبط اسم الملف بالمرة التالية التي نُنشِئ خلالها صندوق نافذة ملف. إذا كان editFile مُتغيّر نسخة يحتوي على الملف الذي اختاره المُستخدِم، وإذا لم يَكُن ذلك الملف فارغًا، فسيُعيد الاستدعاء editFile.getName()‎ سلسلةً نصيةً من النوع String وتُمثِّل اسم الملف؛ في حين سيُعيد الاستدعاء editFile.getParent()‎ كائنًا من النوع File يُمثِّل المجلد المُتضمِّن لذلك الملف. ننتقل الآن للسؤال التالي: ما الذي ينبغي فعله في حالة حدوث خطأ بينما نقرأ الملف المَعنِيّ أو نكْتُب به؟ ينبغي عمومًا التقاط ذلك الخطأ وتبليغ المُستخدِم عن حدوثه؛ فإذا كان البرنامج مُدعَّمًا بواجهة مُستخدِم رسومية، فيُعرَض عادةً للمُستخدِم صندوق نافذةٍ آخر يحتوي على رسالة الخطأ مع زر "OK" لغلق الصندوق. لم نتعرَّض لصناديق النوافذ سابقًا، ولكن يُمكِننا في العموم إنشاء كائناتٍ من الصنف Alert المُعرَّف بحزمة javafx.scene.control بسهولة لنَعرِض بعضًا من أكثر صناديق النوافذ البسيطة شيوعًا. تَعرِض الشيفرة التالية طريقة عرض صندوق نافذة يحتوي على رسالة خطأ: Alert errorAlert = new Alert( Alert.AlertType.ERROR, message ); errorAlert.showAndWait(); يُمكِننا أن نُجمِّع كل ما سبق لنكتُب البرنامج الفرعي النموذجي التالي المسؤول عن حفظ البيانات بملف، حيث يَستخدِم البرنامج الصنف FileChooser لاختيار الملف، والصنف PrintWriter لكتابة البيانات بصيغةٍ نصية: private void doSave() { FileChooser fileDialog = new FileChooser(); if (editFile == null) { // 1 fileDialog.setInitialFileName("filename.txt"); fileDialog.setInitialDirectory( new File( System.getProperty("user.home")) ); } else { // 2 fileDialog.setInitialFileName(editFile.getName()); fileDialog.setInitialDirectory(editFile.getParentFile()); } fileDialog.setTitle("Select File to be Saved"); File selectedFile = fileDialog.showSaveDialog(mainWindow); if ( selectedFile == null ) return; // لم يختر المستخدم ملفًا // 3 PrintWriter out; try { FileWriter stream = new FileWriter(selectedFile); out = new PrintWriter( stream ); } catch (Exception e) { // لا يملُك المُستخدِم على الأغلب صلاحيةً للكتابة بالملف Alert errorAlert = new Alert(Alert.AlertType.ERROR, "Sorry, but an error occurred while\n" + trying to open the file for output."); errorAlert.showAndWait(); return; } try { . . // ‫اكتب النص إلى الملف باستخدام PrintWriter //WRITE TEXT TO THE FILE, using the PrintWriter . out.flush(); // ‫هل هي ضرورية؟ ربما ستُنجز من خلال الأمر ()out.close out.close(); if (out.checkError()) // افحص الأخطاء المحتملة (need to check for errors in PrintWriter) throw new IOException("Error check failed."); editFile = selectedFile; } catch (Exception e) { Alert errorAlert = new Alert(Alert.AlertType.ERROR, "Sorry, but an error occurred while\n" + "trying to write data to the file."); errorAlert.showAndWait(); } } حيث: [1]: لم يُعدَّل أي ملف. اضبط اسم الملف إلى "filename.txt" واسم المجلد إلى المجلد الرئيسي للمُستخدِم. [2]: استرجع اسم الملف والمجلد لصندوق النافذة من الملف الذي يُعدِّله المُستخدِم حاليًا. [3]: ملاحظة: لقد اختار المُستخدِم ملفًا، وفي حال وجود ملفٍ بنفس الاسم، فإنه قد أكّد بالفعل على رغبته بحذف الملف الموجود. يُمكِننا تطبيق نفس الفكرة على الملفات غير النصية، مع استخدام نوعٍ مختلف من مجاري الخرج. تَعمَل قراءة البيانات من ملفٍ معينٍ بنفس الأسلوب، ولهذا لن نناقش التابع المكافئ doOpen()‎. يُمكِنك مع ذلك الإطلاع على البرنامج التوضيحي TrivialEdit.java، حيث ستَجِد برامجًا فرعية subroutines مسؤولةً عن فتح الملفات النصية وحفظها، كما يَسمَح هذا البرنامج للمُستخدِم بتعديل بعض الملفات النصية الصغيرة، وتعديل البرامج الفرعية المُعرَّفة ضمنه، وإعادة اِستخدَامها ضمن برامج واجهات مُستخدِم رسومية GUI أخرى تتعامل مع الملفات. ترجمة -بتصرّف- للقسم Section 2: Files من فصل Chapter 11: Input/Output Streams, Files, and Networking من كتاب Introduction to Programming Using Java. اقرأ أيضًا المقال التالي: معالجة الملفات في جافا المقال السابق: قنوات الدخل والخرج وعمليتي القراءة والكتابة في جافا كتابة أصناف وتوابع معممة في جافا الواجهات Interfaces في جافا التعاود recursion في جافا
    1 نقطة
×
×
  • أضف...