0% found this document useful (0 votes)
90 views113 pages

Learn Java

Uploaded by

Yousef Suliman
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
90 views113 pages

Learn Java

Uploaded by

Yousef Suliman
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 113

‫أول إصدار‪ :‬ذي القعدة ‪ 1433‬هجرية الموافق أكتوبر ‪ 2012‬ميلداية‬

‫اﻹصدار الحالي‪ :‬ربيع ثاني ‪ 1439‬هجرية الموافق ‪ 7‬يناير ‪ 2018‬ميلداية‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫مقدمة‬
‫بسم الله الرحمن الرحيم والصلة والسلم على أشرف اﻷنبياء والمرسلين‪ ،‬نبينا محمد وعلى آله وصحبه أجمعين‪.‬‬
‫أما بعد‪ .‬الهدف من هذا الكتاب تعريف المبرمج في فترة وجيزة وكمدخل سريع للغة البرمجة جافا باستخدام أداة‬
‫التطوير ‪ .NetBeans‬ثم يتم التعمق تدريجياا في المفاهيم اﻷساسية في اللغة والبرمجة عموماا‪ .‬وبهذا يكون هذا‬
‫اليكتيب موجه فقط لمن لديه خبرة في لغة برمجة أخرى حتى لو كانت قليلة‪ .‬كذلك ييمكن اﻹستفادة من هذا الكتاب‬
‫كمقدمة لتعلم برمجة الموبايل بإستخدام جافا‪ ،‬مثل نظام أندرويد أو جافا موبايل وذلك ﻷن أساس اللغة واحد‪.‬‬

‫لغة جافا‬
‫لغة جافا ظهرت في عام ‪) 1995‬أي قبل أكثر من عشرين عاماا( وهي لغة متعددة اﻷغراض ومتعددة المنصات تصلح‬
‫لعدد كبير من التطبيقات‪ .‬ومترجم جافا يقوم بإنتاج ملفات في شكل ‪ Byte code‬وهو يختلف عن الملفات‬
‫التفيذية التي تنتج عن لغات البرمجة اﻷخرى مثل سي وباسكال‪ .‬وتحتاج البرامج المكتوبة بلغة جافا إلى منصة‬
‫في أنظمة التشغيل المختلفة لتتمكن برامجها من العمل في هذه اﻷنظمة‪ .‬وهذه المنصة يتسمة آلة جافا اﻹفتراضية‬
‫‪ Java Virtual Machine‬أو إختصاراا بـ ‪ JVM‬أو ‪.Java Run-time‬‬

‫آلة جافا اﻹفتراضية ‪JVM‬‬


‫تتوفر هذه المنصة في عدد كبير من أنظمة التشغيل‪ ،‬ولبد من التأكد من وجود هذه المنصة أو اللة اﻹفتراضية‬
‫قبل تشغيل برنامج جافا‪ .‬وكل نظام تشغيل يحتاج للة إفتراضية خاصة به‪ .‬مثلا نظام وندوز ‪ 32‬بت يحتاج للة‬
‫إفتراضية مخصصة لوندوز ‪ 32‬بت‪ ،‬ووندوز ‪ 64‬بت يحتاج للة إفتراضية ‪ 64‬بت‪ .‬وهذا مثال ﻹسم ملف لتثبيت آلة‬
‫جافا اﻹفتراضية لنظام وندوز ‪ 64‬بت‪:‬‬

‫‪jre­8u51­windows­x64.exe‬‬

‫وهو ييمثل نسخة جافا ‪ 1.8‬أو ماييسمى جافا ‪ 8‬وهي آخر نسخة من الجافا متوفرة لحظة إعادة تحرير هذا الكتاب‪.‬‬

‫واسم الملف التالي ييمثل حزمة تحتوي على اللة اﻹفتراضية لجافا ‪ 8‬لنظام أوبونتو ‪:‬‬
‫‪openjdk­8­jre‬‬
‫وتختلف معماريتها حسب معمارية نظام أوبونتو‪ ،‬فإذا كان النظام هو ‪ 32‬بت تكون حزمة جافا ‪ 32‬بت‪ ،‬وإذا كان ‪64‬‬
‫بت تكون حزمة جافا ‪ 64‬بت‪ .‬لكن يمكن تثبيت جافا ‪ 32‬بت في نظام أوبونتو ‪ 64‬بت ‪ -‬كذلك في نظام وندوز‪-‬‬
‫وذلك ﻷن بعض البرامج تتطلب جافا ‪ 32‬بت‪ ،‬لكن ل يمكن تثبيت جافا ‪ 64‬بت في نظام تشغيل ‪ 32‬بت‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫عند إنتاج برامج جافا ييمكن تشغيلها في أي نظام تشغيل مباشرة عند وجود اللة اﻹفتراضية المناسبة‪ ،‬ول يحتاج‬
‫البرنامج ﻹعادة ترجمة حتى يعمل في أنظمة غير النظام الذي تم تطوير البرنامج فيه‪ .‬مثلا ييمكن تطوير برنامج‬
‫جافا في بيئة لينكس ﻹنتاج برامج يتم نقلها وتشغيلها مباشرة في وندوز أو ماكنتوش‪ .‬وتختلف عنها لغة سي‬
‫وأوبجكت باسكال في أنها تحتاج ﻹعادة ترجمة البرامج مرة أخرى في كل نظام تشغيل على حده قبل تشغيل تلك‬
‫البرامج‪ .‬لكن برامج لغة سي وأوبجكت باسكال لتحتاج للة إفتراضية في أنظمة التشغيل بل تتعامل مع نظام‬
‫التشغيل ومكتباته مباشرة‪.‬‬

‫أداوات تطوير جافا ‪Java SDK‬‬


‫آلة جافا اﻹفتراضية السابقة يتمككن برامج جافا من العمل في نظام التشغيل‪ ،‬لكنها ل تحتوي على مترجم‪ ،‬لذلك ل‬
‫يمكن كتابة برامج جافا وتطويرها بها‪ ،‬ولتطوير وترجمة وتنقيح برامج جافا وتحويلها إلى ‪ byte code‬لبد من‬
‫الحصول على الـ ‪ SDK‬الخاص بالجافا‪ ،‬أي ماييعرف بـالـ ‪ .Java SDK‬وهو يأتي في شكل برنامج للتثبيت به مترجم‬
‫جافا )‪ ،(compiler‬ومنقح )‪ ،(debugger‬وآلة جافا اﻹفتراضية‪ ،‬أي لنحتاج لتثبيت آلة جافا اﻹفتراضية لوحدها‬
‫عند تثبيت ‪ .Java SDK‬واسم الملف التالي ييمثل الـ ‪ Java SDK‬لبيئة وندوز‪:‬‬
‫‪jdk­7u51­windows­x64.exe‬‬
‫وهو مخصص لنظام وندوز ‪ 64‬بت وييمكثل جافا ‪ .7‬وينلحظ أنه يبدأ باﻹسم ‪ jdk‬وهو إختصار لـ ‪Java‬‬
‫‪.Development Kit‬‬
‫والملف التالي ييمثل حزمة ‪ Java SDK‬لنظام التشغيل أوبونتو‪:‬‬
‫‪openjdk­8­jdk‬‬

‫بيئة التطوير ‪NetBeans‬‬


‫وهي من أفضل بيئات التطوير للغة جافا‪ ،‬وقد تمت كتابتها باستخدام لغة جافا نفسها بواسطة شركة أوراكل‬
‫صاحبة تلك اللغة‪.‬‬
‫ييمكن استخدام هذه اﻷداة لتطوير برامج بلغات برمجة أخرى غير الجافا مثل برامج ‪ PHP‬و سي‪.++‬‬

‫توجد أدوات تطوير أخرى مشهورة و هي ‪ Eclipse‬وهي مستخدمة من قبل مبرمجين يكثر‪ ،‬و أخرى تسمى ‪IntelliJ‬‬
‫والتي يبنيت عليها بيئة تطوير أندرويد‪.‬‬
‫جميع بيئات التطوير هذه تحتاج إلى تثبيت ‪ Java SDK‬أولا قبل تثبيتها‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫المؤلف‪ :‬معتز عبدالعظيم‬
‫أعمل مطور برامج ومعماري أنظمة‪ ،‬وقد يكنت استخدم فقط لغة أوبجكت باسكال كلغة برمجة أساسية‪ ،‬متمثلة في‬
‫دلفي وفري باسكال‪ ،‬لكن منذ عام ‪ 2011‬بدأت تعلم جافا وكتبت بها عدد من البرامج‪ .‬وكان سبب تعلمي لها‬
‫واعتمادي لها في تطوير كثير من البرامج هو‪:‬‬
‫‪ .1‬أنه يوجد عدد كبير من المبرمجين يستخدمون لغة جافا‪ ،‬بل أن معظمهم درسها في الجامعة‪ .‬لذلك ييمكن‬
‫أن تكون لغة مشتركة بين عدد كبير من المبرمجين‪.‬‬
‫‪ .2‬توجد مكتبات كثيرة ومجانية تدعم مجال اﻹتصالت مكتوبة بلغة جافا‪ ،‬وهو المجال الذي أعمل فيه‪.‬‬
‫‪ .3‬أنها مجانية ويتوفر لها أدوات تطوير متكاملة ذات إمكانات عالية في عدد من المنصات‪ .‬ماعلى المبرمج إل‬
‫إختيار المنصة المناسبة له‬
‫‪ .4‬تدعم البرمجة الكائنية بصورة قوية‪ ،‬والبرمجة الكائنية تشكل أداة أساسية لتطوير البرامج بطريقة مثالية‪.‬‬
‫‪ .5‬أن البرامج الناتجة عنها متعددة المنصات والمعماريات بمعنى الكلمة‪ ،‬وليحتاج اليمبرمج إنتاج عدد من‬
‫الملفات التنفيذية لكل معمارية على حده‪ .‬بل يحتاج ﻹنتاج ملف ‪ byte code‬واحد يكفي لمعظم‬
‫المعماريات وأنظمة تشغيل الكمبيوتر المعروفة‪.‬‬
‫‪ .6‬أداة التطوير ‪ Netbeans‬وطريقة تقسيم الحزم ‪ packages‬مناسبة للبرامج الكبيرة والتي تحتاج تقسيماا‬
‫منطقياا والوصول لتلك اﻷقسام بسرعة وسهولة ويتسهل أيضاا التشارك في كتابة البرامج‪.‬‬

‫ترخيص الكتاب‬
‫هذا الكتاب مجاني تحت ترخيص‬
‫‪creative commons‬‬
‫‪CC BY-SA 3.0‬‬

‫ملحوظة‬

‫ل ييفُضضلّ نسخ ثم اللصق في بيئة ‪ NetBeans‬من هذا الكتاب لنه يتم أحيان ا ا نقلّ أحرف غير مرئية تتسب في تعثر ترجمة البرامج‪ .‬لذلك من‬
‫الفضلّ كتابة المثلة يدوياا‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫المحتويات‬
‫مقدمة ‪2.....................................................................................................................................................................‬‬
‫لغة جافا ‪2..................................................................................................................................................................‬‬
‫آلة جافا اﻹفتراضية ‪2........................................................................................................................................ JVM‬‬
‫أدوات تطوير جافا ‪3................................................................................................................................ Java SDK‬‬
‫بيئة التطوير ‪3........................................................................................................................................ NetBeans‬‬
‫المؤلف‪ :‬معتز عبدالعظيم ‪4.........................................................................................................................................‬‬
‫ترخيص الكتاب ‪4.......................................................................................................................................................‬‬
‫تثبيت جافا و ‪7...................................................................................................................................... NetBeans‬‬
‫البرنامج اﻷول‪9........................................................................................................................................................ .‬‬
‫برنامج الواجهة رسومية ‪16.......................................................................................................................................‬‬
‫الفورم الثاني ‪19.........................................................................................................................................................‬‬
‫الملفات ‪21..................................................................................................................................................................‬‬
‫كتابة نص في ملف ‪23...............................................................................................................................................‬‬
‫القراءة من ملف نصي ‪26...........................................................................................................................................‬‬
‫استعراض الملفات ‪29.................................................................................................................................................‬‬
‫سلسلة البيانات ‪30...................................................................................................................................... Stream‬‬
‫نسخ الملفات ‪31.........................................................................................................................................................‬‬
‫الخصائص ‪34........................................................................................................................................ Properties‬‬
‫المصفوفات ‪37.............................................................................................................................................. arrays‬‬
‫السلسل ‪38............................................................................................................................................. ArrayList‬‬
‫تعريف الكائنات والذاكرة ‪41.......................................................................................................................................‬‬
‫برنامج اختيار الملف ‪44.............................................................................................................................................‬‬
‫كتابة فئة كائن جديد ‪47........................................................................................................................ New Class‬‬
‫المتغيرات واﻹجراءات الساكنة )‪51............................................................................................................... (static‬‬
‫قاعدة البيانات ‪53........................................................................................................................................ SQLite‬‬
‫برنامج لقراءة قاعدة بيانات ‪54.................................................................................................................... SQLite‬‬
‫الوراثة ‪63........................................................................................................................................... inheritance‬‬
‫تكرار حدث بواسطة مؤقت ‪67...................................................................................................................................‬‬
‫برمجة الويب باستخدام جافا ‪71...............................................................................................................................‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫تثبيت مخدم الويب ‪71..............................................................................................................................................‬‬
‫أول برنامج ويب ‪75...................................................................................................................................................‬‬
‫تثبيت برامج الويب ‪79..............................................................................................................................................‬‬
‫تقنية ‪80.............................................................................................................................................................. JSP‬‬
‫خدمات الويب ‪84............................................................................................................................ Web services‬‬
‫برنامج خدمة ويب للكتابة في ملف ‪86......................................................................................................................‬‬
‫برنامج عميل خدمة ويب ‪94......................................................................................................................................‬‬
‫القراءة من مخدم ويب بواسطة ‪98................................................................................................................ HTTP‬‬
‫خدمات ويب الـ ‪100................................................................................................................................. RESTFull‬‬
‫استخدام نسق ‪108.......................................................................................................................................... JSON‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫تثبيت جافا و ‪NetBeans‬‬
‫قبل بداية تطوير البرامج باستخدام لغة جافا وأداة التطوير ‪ NetBeans‬لبد من تثبيتها بالطريقة التالية حسب‬
‫نظام التشغيل‪:‬‬

‫تثبيت جافا ‪ SDK‬في نظام لينكس )أبونتو‪ ،‬أو دبيان ومشتقاتها(‪:‬‬

‫‪sudo apt­get install openjdk­8­jdk‬‬


‫بهذه الطريقة يتم تثبيت حزمة جافا ‪ 8‬في نظام أوبونتو أو دبيان‪.‬‬
‫بعد أو قبل ذلك يمكننا التأكد من أن آلة جافا اﻹفتراضية موجودة باستخدام اﻷمر‪:‬‬
‫‪java ­version‬‬
‫فإذا كانت النتيجة كالتالي‪:‬‬
‫"‪openjdk version "1.8.0_91‬‬
‫)‪OpenJDK Runtime Environment (build 1.8.0_91­8u91­b14­0ubuntu4~14.04­b14‬‬
‫)‪OpenJDK 64­Bit Server VM (build 25.91­b14, mixed mode‬‬
‫فهي تعني أن جافا ‪ 8‬مثبتة‪.‬‬
‫ثم نتأكد من أن مترجم جافا موجود‪:‬‬
‫‪javac ­version‬‬
‫فإذا كانت النتيجة كالتالي‪:‬‬
‫‪javac 1.7.0_111‬‬
‫فهي تعني أن مترجم جافا ‪ 8‬مثبت‪ .‬إذا تحصلنا على تلك النتائج قبل تثبيت جافا فهي تعني أن جافا موجودة في‬
‫نظام التشغيل‪ .‬بعد اﻷنظمة مثل ‪ Linuxmint‬و ‪ Raspbian‬المستخدمة مع راسبري باي‪ ،‬تأي محملة مسبقاا بآلة‬
‫جافا اﻹفتراضية واحياناا المترجم‪.‬‬

‫تثبيت جافا ‪ SDK‬في نظام وندوز‪:‬‬


‫يمكننا تجربة أوامر التأكد من وجود جافا والمترجم في الطرفية‪ ،‬فإذا لم تكن موجودة نتحصل عليها من موقع‬
‫جافا ‪ www.java.com‬أو من موقع شركة أوراكل‪ .‬يمكن البحث عنها أولا بدللة هذه الجملة‪:‬‬
‫‪download java sdk for windows‬‬
‫ثم نتأكد أننا قمنا باختيار ملف ييمثل نظام وندوز الذي نستخدمه‪ ،‬فإذا كان وندوز ‪ 32‬بت فلبد من اختيار جافا ‪32‬‬
‫بت‪ ،‬وهكذا‪ ،‬ونتأكد أيضاا أن الملف يحتوي على المقطع )‪ (sdk‬ﻷن )‪ (jre‬تحتي فقط على اللة اﻹفتراضية ول‬
‫تحتوي على المترجم‪ .‬مثلا الملف أدناه ييمثل جافا ‪ SDK 8‬لنظام وندوز ‪ 64‬بت‪:‬‬
‫‪jdk­8u101­windows­x64.exe‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫بعد ذلك نقوم بتثبيت ‪ NetBeans‬بعد الحصول عليها من موقع ‪ .netbeans.org‬ول بد من أن نختار النسخة‬
‫المناسبة لنظام التشغيل‪ ،‬واختيار النسخة التي تحوي على كافة الميزات‪ ،‬منها برمجة الويب‬
‫)مكتوب أمامها ‪.(Java EE‬‬
‫في بداية التثبيت لبد من اختيار ‪ Custmize‬ثم اختيار ‪ Apache Tomcat‬بدلا من ‪ Glassfsh‬حيث سوف‬
‫نستخدم ‪ Apache Tomcat‬كمخدم ويب لحقاا‪:‬‬

‫ثم بعد ذلك في الشاشة التالية لبد من التأكد من اختيار جافا ‪:SDK‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


.‫البرنامج اﻷول‬
Java/Java ‫ ثم‬New/Project ‫ نقوم باختيار‬NetBeans ‫بعد تثبيت آلة جافا اﻹفتراضية وأداة التطوير‬
:‫ ليظهر لنا الكود التالي‬hello ‫ ثم نقوم بتسمية البرنامج‬.Application

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;

/*
*
* @author motaz
*/
public class Hello {

/*
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
}
‫ كما‬NetBeans ‫ بواسطة شاشة المشروع التي تظهر يسار شاشة‬hello.java ‫فإذا لم يظهر الكود نقوم بفتح الملف‬
:‫في الشكل التالي‬

Code.sd ‫كود لبرمجيات الكبيوتر‬


main ‫بعد ذلك نقوم بكتابة السطر التالي داخل اﻹجراء‬
System.out.print("Hello Java world\n");
:‫ليصبح الكود كالتالي‬
package hello;

/**
*
* @author motaz
*/
public class Hello {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
System.out.print("Hello Java world\n");

}
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫يتم تشغيل البرنامج عن طريق المفتاح ‪ F6‬ليظهر لنا اليمخرجات في أسفل شاشة ‪NetBeans‬‬

‫اﻷمر ‪ System.out.print‬يقوم بكتابة نص أو متغير في شاشة الطرفية‪.‬‬


‫الرمز ‪ \n‬مهمته هو اﻹنتقال للسطر الجديد في الطرفية‪ ،‬يمكن استخدام ‪ println‬والذي يقوم باﻹنتقال للسطر‬
‫الجديد دون الحاجة ﻹستخدام رمز السطر الجديد ‪ \n‬ليصبح اﻷمر كالتالي‪:‬‬

‫;)"‪System.out.println("Hello Java world‬‬

‫لتشغيل البرنامج الناتج خارج بيئة التطوير‪ ،‬نقوم أولا ببناء الملف التفنيذي بواسطة ‪ Build‬وذلك بالضغط على‬
‫المفاتيح ‪ . Shift + F11‬بعدها نبحث عن الدليل الذي يحتوي على برامج ‪ NetBeans‬ويكون اسمه في الغالب‬
‫‪ NetBeansProjects‬ثم داخل الدليل ‪ hello‬نجد دليل اسمه ‪ dist‬يحتوي على الملف التنفيذي‪ .‬في هذه الحالة‬
‫يكون اسمه ‪hello.jar‬‬
‫ييمكن تنفيذ هذا البرنامج في سطر اﻷوامر في نظام التشغيل بواسطة كتابة اﻷمر التالي‪:‬‬
‫‪java ­jar hello.jar‬‬
‫ييمكن نقل هذا الملف التنفيذي من نوع ‪ Byte code‬إلى أي نظام تشغيل آخر يحتوي على آلة جافا اﻹفتراضية ثم‬
‫تنفيذه بهذه الطريقة‪ .‬وينلحظ أن حجم الملف التنفيذي صغير نسبياا )حوالي كيلو ونصف( وذلك ﻷننا لم نستخدم‬
‫مكتبات إضافية‪.‬‬
‫بعد ذلك نقوم بتغيير الكود إلى التالي‪:‬‬

‫;‪int num = 9‬‬


‫;)‪System.out.println(num + " * 2 = " + num * 2‬‬
‫وهذه طريقة لتعريف متغير صحيح أسميناه ‪ num‬وأسندنا له قيمة إبتدائية ‪9‬‬
‫وفي السطر الذي يليه يقمنا بكتابة قيمة المتغير‪ ،‬ثم كتابة قيمته مضروبة في الرقم ‪ .2‬وهذا هو ناتج تشغيل‬
‫البرنامج‪:‬‬
‫‪9 * 2 = 18‬‬

‫لطباعة التاريخ والساعة الحاليين نكتب هذه اﻷسطر‪:‬‬


‫;)(‪Date today = new Date‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


System.out.println("Today is: " + today.toString());

:‫ في بداية البرنامج‬Date ‫ولبد من إضافة المكتبة المحتوية على الفئة‬


import java.util.Date;

:‫فيصبح شكل كود البرنامج الكلي هو‬

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;

import java.util.Date;

public class Hello {

/*
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int num = 9;

System.out.println(num + " * 2 = " + num * 2);


Date today = new Date();
System.out.println("Today is: " + today.toString());

}
}
: ‫وهذا هو ناتج تشغيل البرنامج‬

9 * 2 = 18
Today is: Fri Jul 31 11:59:46 EAT 2015

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫ملحوظة‪:‬‬
‫ييمكن إضافة إسم المكتبة تلقائياا عند ظهور العلمة الصفراء شمال السطر الموجودة فيه الفئة ‪ Class‬التي تحتاج‬
‫لتلك المكتبة كما تظهر في هذه الصورة‪:‬‬

‫ثم اختيار ‪Add import for java.util.Date‬‬


‫وهذه ميزة مهمة في أي أداة تطوير تغني عن حفظ أسماء المكتبات المختلفة أو إضافتها يدوياا‪.‬‬
‫يمكن تغيير نسق التاريخ والساعة وذلك باستخدام الكائن ‪ SimpleDateTime‬كما في المثال التالي‪:‬‬

‫;)"‪SimpleDateFormat simpleFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss‬‬


‫;)(‪Date today = new Date‬‬
‫))‪System.out.println("Today is: " + simpleFormat.format(today‬‬

‫والناتج هو‪:‬‬
‫‪Today is: 31.07.2015 12:03‬‬

‫ويمكن تغيير النسق بتغيير موضع الرموز التي ترمز لمكونات التاريخ وهي‪:‬‬
‫‪ dd‬ييمثل اليوم‬
‫‪ MM‬ييمثل رقم الشهر‬
‫‪ yyyy‬ييمثل السنة كاملة‪ ،‬يمكن اختصارها في ‪ yy‬لتصبح رقمين فقط‪ ،‬مثلا ‪ 15‬والتي تعني ‪2015‬‬
‫‪ :HH‬الساعة بنسق ‪ 24‬ساعة‬
‫‪ :mm‬الدقائق‬
‫‪ :ss‬الثواني‬

‫وهذا مثال آخر لنسق مختلف‬


‫;)"‪SimpleDateFormat simpleFormat = new SimpleDateFormat("E dd.MMMM.yyyy hh:mm:ss a‬‬
‫;)(‪Date today = new Date‬‬
‫;))‪System.out.println("Today is: " + simpleFormat.format(today‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫وهذا هو الناتج‪:‬‬
‫‪Today is: Fri 31.July.2015 12:10:21 PM‬‬

‫استخدمنا ‪ E‬لكتابة اليوم من اﻹسبوع‪ ،‬و ‪ MMMM‬لكتابة اسم الشهر كام ا‬


‫ل‪ ،‬ويمكن استخدام ‪ MMM‬لكتابة اسم‬
‫الشهر بطريقة مختصرة‪ ،‬واستخدمنا ‪ h‬لكتابة الساعة بنسة ‪ 12‬ساعة‪ ،‬ول بد من استخدام ‪ a‬معها لتوضيح هل هو‬
‫مسااء أم صباحاا ‪am/pm‬‬

‫يمكن استخدام ‪ SimpleDateFormat‬لتحويل التاريخ من شكل نص ‪ String‬إلى تاريخ ‪ Date‬وذلك باستخدام‬


‫الدالة ‪ parse‬لكن لبد من مطابقة النسق وإل حدث خطأ‪:‬‬
‫{ ‪public static void main(String[] args) throws ParseException‬‬

‫;"‪String todayStr = "15.10.2012‬‬


‫;)"‪SimpleDateFormat simpleFormat = new SimpleDateFormat("dd.mm.yyyy‬‬
‫;)‪Date today = simpleFormat.parse(todayStr‬‬
‫;))‪System.out.println("Today is: " + simpleFormat.format(today‬‬
‫}‬
‫نلحظ أننا قمنا بإضافة ‪ throws ParseException‬في بداية الدالة ‪ main‬وذلك بعد أن أقترحت علينا بيئة‬
‫التطوير هذه اﻹضافة وذلك ﻷن عملية التحويل هذه ربما ينتج عنها خطأ إذا كانت القيمة المدخلة غير صحيحة أو‬
‫تحتوي على أحرف مثلا أو قيم تاريخ غير صحيحة مثلا تم إدخال ‪ 15‬في خانة الشهر أو ‪ 32‬خانة اﻷيام‪ ،‬أو ربما‬
‫تم إدخال تاريخ بغير النسق‪ ،‬مثلا ‪ .15/10/2012‬وسوف نتكلم لحقاا على معالجة اﻹستثناءات في لغة جافا في‬
‫هذا الكتاب بإذن الله‪.‬‬

‫في المثال التالي يقمنا بتغيير لون جزء من النص بالطريقة التالية‪:‬‬

‫;)" ‪System.out.print("Changing text color in‬‬


‫‪System.out.print("\033[31m"); // Change color to red‬‬
‫;)" ‪System.out.print("java‬‬
‫‪System.out.print("\033[34m"); // Change to blue‬‬
‫;)"‪System.out.print("console application‬‬
‫‪System.out.println("\033[0m"); // change to default color‬‬
‫فتظهر النتيجة بالشكل التالي في بيئة ‪:NetBeans‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫وتظهر بالشكل التالي عند تنفيذ البرنامج من الطرفية‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫برنامج الواجهة رسومية‬
‫من اﻷشياء المهمة في أدوات التطوير و لغات البرمجة هو دعمها للواجهات الرسومية أو ماييسمى بالـ ‪.Widgets‬‬
‫كل نظام تشغيل يحتوي على مكتبة أو أكثر يتمثل واجهة رسومية‪ ،‬مثلا يوجد في نظام لينكس واجهات ‪ GTK‬و‬
‫‪ QT‬و في نظام وندوز توجد مكتبة وندوز الرسومية‪ ،‬وفي نظام ماكنتوش توجد مكتبات ‪ Carbon‬و ‪ .Cocoa‬أما‬
‫جافا فلها مكتباتها الخاصة والتي تعمل في كل هذه اﻷنظمة ومنها واجهة ‪.Swing‬‬

‫لكتابة أول برنامج ذو واجهة رسومية في جافا باستخدام ‪ NetBeans‬نختار ‪File/New Project‬‬
‫ثم نختار ‪Java/Java Application‬‬
‫ونقوم بتسميته مثلا ‪.mygui‬‬
‫في شاشة ‪ Projects‬نختار الحزمة ‪ mygui‬ثم بالزر اليمين للماوس نختار ‪New/JFrame Form‬‬
‫نسمى هذا الفورم ‪ MainForm‬فيتم إضافته للمشروع ويظهر بالشكل التالي‪:‬‬

‫يظهر الفورم الرئيسي المسمى ‪ MainForm.java‬في وسط الشاشة‪ .‬وفي اليمين نلحظ وجود عدد من المكونات‬
‫في صفحة الـ ‪ .Palette‬نقوم بإدراج زر ‪ Button‬في وسط الفورم الرئيسي‪ ،‬ثم نقوم بتغيير عنوانه إلى ‪،Hello‬‬
‫وذلك إما بالضغط على زر ‪ F2‬ثم تغيير العنوان‪ ،‬أو بالنقر على الزر اليمين في الماوس في هذا الزر ثم نختار‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫‪ Properties‬ثم ‪Text‬‬

‫نرجع مرة أخرى للخصائص لنضيف حدث عند الضغط على الزر‪ .‬هذه المرة نختار ‪ Events‬ثم في الخيار‬
‫‪ actionPerformed‬نختار الحدث ‪ jButton1ActionPerformed‬بعدها يظهر هذا الكود في شاشة الـ ‪:Source‬‬

‫{ )‪private void jButton1ActionPerformed(java.awt.event.ActionEvent evt‬‬


‫‪// TODO add your handling code here:‬‬
‫}‬
‫أو ييمكن إظهار هذا الكود بواسطة النقر المزدوج على الزر ‪double click‬‬
‫فنقوم بتكابة كود ﻹظهار عبارة )السلم عليكم( عند الضغط على هذا الزر‪ .‬فيصبح الكود الحدث كالتالي‪:‬‬

‫{ )‪private void jButton1ActionPerformed(java.awt.event.ActionEvent evt‬‬


‫;"السلم عليكم" = ‪String msg‬‬
‫;)‪JOptionPane.showMessageDialog(null, msg‬‬
‫}‬

‫نلحظ أننا يقمنا بتعريفا المتغير ‪ msg‬من النوع المقطعي ‪ String‬ثم يقمنا بإسناد قيمة إبتدائية له‪“ :‬السلم عليكم”‬
‫بعد ذلك نرجع للحزمة الرئيسية ‪ Mygui.java‬ثم نكتب الكود التالي في اﻹجراء ‪:main‬‬

‫{ )‪public static void main(String[] args‬‬


‫;)(‪MainForm form = new MainForm‬‬
‫;)‪form.setVisible(true‬‬
‫}‬
‫في السطر اﻷول ينعكرف الكائن ‪ form‬من النوع ‪ MainForm‬الذي يقمنا بتصميمه‪ ،‬ثم نقوم بإنشاء نسخة من هذا‬
‫النوع و تهيئته بواسطة‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫‪new MainForm‬‬
‫وفي السطر الثاني قمنا بإظهار الفورم في الشاشة‪.‬‬
‫عند تنفيذ البرنامج يظهر بالشكل التالي عند الضغط على الزر‪:‬‬

‫نرجع مرة أخرى للفورم في شاشة التصميم )‪ (Design‬ونقوم بإدراج المكون ‪ TextField‬ليندخل فيه إسم‬
‫المستخدم‪ ،‬ثم مكون من نوع ‪ Label‬نكتب فيه كلمة )اﻹسم( ثم مكون آخر من نوع ‪ Label‬نقوم بتغير إسمه إلى‬
‫‪ jlName‬وذلك في فورم الخصائص في صفحة ‪ Code‬في‬
‫قيمة ‪Variable Name‬‬
‫ثم يندرج زر نكتب فيه كلمة )ترحيب( كما في الشكل التالي‪:‬‬

‫في الحدث ‪ ActionPerfomed‬لهذا الزر الجديد )ترحيب( نكتب الكود التالي لكتابة إسم المستخدم في المكون‬
‫‪jLabel2‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫{ )‪private void jButton2ActionPerformed(java.awt.event.ActionEvent evt‬‬

‫;))(‪ " + jTextField1.getText‬مرحبا ا بك"(‪jlName.setText‬‬


‫}‬
‫نلحظ أن اﻹجراء ‪ getText‬ييستخدم لقراءة محتويات الحقل النصي ‪ Text Field‬واﻹجراء ‪ setText‬يقوم‬
‫بتغيير النص للمكون ‪.Label‬‬

‫الفورم الثاني‬
‫ﻹضافة وإظهار فورم ثاني في نفس البرنامج‪ ،‬نتبع الخطوات في المثال التالي‪:‬‬
‫نقوم بإضافة ‪ JFrame Form‬ونسميه ‪ SecondFrom‬ونضع فيه ‪ Label‬نكتب فيه عبارة "‪”Second Form‬‬
‫ونزريد حجم الخط في هذا العنوان بواسطة ‪.Properties/Font‬‬

‫في خصائص هذا الفورم الجديد نقوم بتغيير الخاصية ‪ defaultCloseOperation‬إلى ‪ Dispose‬بدلا من‬
‫‪ EXIT_ON_CLOSE‬ﻷننا إذا تركناها في الخيار اﻷخير يتم إغلق البرنامج عندما نغلق الفورم الثاني‪ .‬وجرت‬
‫العادة أن يتم إغلق أي برنامج عند إغلق شاشته الرئيسة‪ .‬إغلق الشاشات الفرعية يفترض به أن يقودنا إلى‬
‫الشاشات الرئيسة‪.‬‬
‫نضيف زر في الفورم الرئيسي ‪ MainForm‬ونكتب الكود التالي في الحدث ‪ ActionPerformed‬في هذا الزر‬
‫الجديد ﻹظهار الفورم الثاني‪ ،‬أو يمكن كتابة هذا الكود في زر الترحيب‪.‬‬
‫;)(‪SecondForm second = new SecondForm‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫;)‪second.setVisible(true‬‬
‫ييمكن إرسال كائن أو متغير للفورم الجديد‪ .‬مثلا نريد كتابة رسالة الترحيب في الفورم الثاني‪.‬‬
‫لعمل ذلك نحتاج لتغير إجراء التهيئة ‪ constructor‬في الفورم الثاني والذي اسمه ‪ ، SecondForm‬نضيف إليه‬
‫مدخلت‪:‬‬
‫{ )‪public SecondForm(String atext‬‬
‫;)(‪initComponents‬‬
‫;)‪jLabel1.setText(atext‬‬
‫}‬
‫ثم نظهر هذه المدخلت – والتي هي عبارة عن رسالة الترحيب – في العنوان ‪jLabel1‬‬
‫وعند تهيئة الفورم الثاني من الفورم الرئيسي نقوم بتعديل إجراء التهيئة إلى الكود التالي‪ ،‬وهذا الكود كتبناه في‬
‫إجراء زر الترحيب‪:‬‬
‫{ )‪private void jButton2ActionPerformed(java.awt.event.ActionEvent evt‬‬
‫;))(‪ " + jTextField1.getText‬مرحبا ا بك"(‪jlName.setText‬‬

‫;))(‪SecondForm second = new SecondForm(jlName.getText‬‬


‫;)‪second.setVisible(true‬‬
‫}‬

‫عند التنفيذ يظهر هذا الشكل‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫الملفات‬
‫التعامل مع الملفات من اﻷشياء اﻷساسية في أي لغة برمجة وفي أي نظام تشغيل‪ .‬و كثير من البرامج تحتاج‬
‫لتخزين بعض البيانات في ملفات على القرص‪ ،‬أو قراءتها‪ ،‬وتشمل العمليات على الملفات‪:‬‬
‫إنشاء ملف جديد‬ ‫•‬
‫الكتابة في ملف‬ ‫•‬
‫قراءة محتويات ملف‬ ‫•‬
‫حذف ملف‬ ‫•‬
‫التأكد من وجود ملف في مسار معين‪.‬‬ ‫•‬
‫عرض أسماء الملفات في مسار معين‬ ‫•‬

‫في المثال التالي سوف نقوم باختبار وجود الملف ‪ myfle.txt‬وإذا لم يكن موجود سوف يقوم البرنامج بإنشاء‬
‫ملف جديد بهذا اﻹسم‪:‬‬

‫{ ‪public static void main(String[] args) throws IOException‬‬

‫;)"‪File file = new File("/home/motaz/myfile.txt‬‬


‫{ ))(‪if (file.exists‬‬
‫;)"‪System.out.println("File exists‬‬
‫}‬
‫{ ‪else‬‬
‫;)"‪System.out.println("File does not exist‬‬
‫;)(‪file.createNewFile‬‬
‫}‬
‫}‬

‫نلحظ أننا استخدمنا عبارة ‪ throws IOException‬في نهاية الدالة الرئيسية ‪ main‬وذلك لحتمال حدوث خطأ‬
‫أثناء إنشاء الملف‪ ،‬مث ا‬
‫ل قد يكون المسار المحدد هو للقراءة فقط‪ ،‬أو ليس للمستخدم الحالي صلحية لكتابة ملف‬
‫في هذا المسار‪ ،‬أو ربما يكون المسار غير موجود في اﻷساس‪.‬‬
‫كذلك استخدمنا النوع ‪ File‬وقمنا بتعريف كائن منها هو ‪ fle‬وذلك لغرض ربط البرنامج بالملف الخارجي على‬
‫القرص‪ .‬ويمكن عمل عدة عمليات للملف مثل الحذف ‪ fle.delete‬او اﻹنشاء ‪ fle.createNewFile‬أو التأكد من‬
‫وجود الملف ‪fle.exists‬‬
‫هذا المثال تمت كتابته في بيئة لينكس‪ ،‬يمكن تغيير المسار بما يناسب نظام التشغيل‪ ،‬مثلا في وندوز يمكن أن‬
‫يكون ‪c:\directory\myfle.txt‬‬
‫بدلا من استخدام عبارة ‪ throws IOException‬كان من الممكن عمل معالجة للخطاء وذلك بالطريقة التالية‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


public static void main(String[] args) {

try {
File file = new File("/home/motaz/myfile.txt");
if (file.exists()) {
System.out.println("File exists");
}
else {
System.out.println("File does not exist");
file.createNewFile();
}
}
catch (Exception ex){
System.err.println("Unable to create file: " +
ex.toString());
}
}

‫ وهي طريقة أفضل ﻹظهار المشكلة كما‬.catch ‫ يتم تحويل التنفيذ إلى جزء‬try ‫فإذا حدث أي خطأ بعد عبارة‬
.‫ بدلا من ترك المترجم يكتب رسالة الخطأ مباشرة للمستخدم‬،‫يريدها المبرمج للمستخدم‬
:‫هذه هي طريقة حماية أي جزء من الكود والذي يمكن أن يكون عرضة للخطاء أثناء التشغيل‬

try{
// ‫الكود المعرض لخطاء التشغيل‬

return (true);

}
catch (Exception e)
{
System.err.println("Error: " + e.getMessage());
return (false); // fail
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫كتابة نص في ملف‬
‫توجد عدة طرق للكتابة أو لقراءة ملف نصي‪ ،‬اخترنا في هذه اﻷملثة أحد هذه الطرق‪ ،‬وهو باستخدام الفئة‬
‫‪ FileWriter‬وهي مخصصة لكتابة نص في ملف‪.‬‬
‫في المثال التالي ينريد الكتابة في ملف نصي باستخدام برنامج بدون واجهة رسومية )‪(console application‬‬
‫وذلك باختيار ‪.Java/Java Application‬‬
‫هذه المرة ينريد كتابة إجراء جديد نعطيه إسم الملف اليمراد إنشاءه والكتابة فيه والنص الذي ينريد كتابته في هذا‬
‫الملف‪.‬‬
‫قمنا بتسمية المشروع ‪ ،fles‬وكتبنا اﻹجراء الجديد أسفل اﻹجراء ‪ main‬الموجود مسبقاا‪ .‬وأسمينا اﻹجراء‬
‫الجديد ‪ writeToTextFile‬وعرفناه بهذه الطريقة‪:‬‬

‫)‪private static boolean writeToTextFile(String aFileName, String text‬‬


‫{‬

‫}‬
‫نلحظ أننا يقمنا بتعريف يمدخلين لهذا اﻹجراء وهما ‪ aFileName‬وهو من النوع النصي ليستقبل إسم الملف المراد‬
‫كتابته‪ ،‬والخر ‪ text‬وهو من النوع النصي أيضاا والذي ييمثل المحتويات اليمراد كتابتها في الملف‪.‬‬
‫ثم نقوم بكتابة الكود التالي داخل هذا اﻹجراء‪:‬‬

‫)‪private static boolean writeToTextFile(String aFileName, String text‬‬


‫{‬
‫{‪try‬‬

‫;)‪File file = new File(aFileName‬‬


‫;)‪FileWriter writer = new FileWriter(file‬‬

‫;)"‪writer.write(text + "\n‬‬
‫;)(‪writer.close‬‬
‫‪return (true); // success‬‬

‫}‬
‫)‪catch (Exception e‬‬
‫{‬
‫;))(‪System.err.println("Error: " + e.getMessage‬‬
‫‪return (false); // fail‬‬
‫}‬

‫}‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫نلحظ أننا يقمنا بإرجاع القيمة ‪ true‬في حال أن الكتابة في الملف تمت بدون حدوت خطأ‪ .‬أما في حالة حدوث‬
‫الخطأ قمنا بإرجع القيمة ‪ false‬وذلك ليعرف من يينادي هذا اﻹجراء أن العملية نجحت أم ل‪.‬‬

‫بالنسبة لتعريف الملف وتعريف طريقة الكتابة عليه يقمنا بكتابة هذين السطرين‪:‬‬

‫;)‪File file = new File(aFileName‬‬


‫;)‪FileWriter writer = new FileWriter(file‬‬

‫في العبارة اﻷولى يقمنا بتعريف الكائن ‪ fle‬من نوع الفئة ‪ File‬وهو كائن للربط مع الملف الخارجي‪ .‬وقد أعطيناه‬
‫إسم الملف في المدخلت‪ .‬وفي العبارة الثانية يقمنا بتعريف الكائن ‪ writer‬من النوع ‪ FileWriter‬المتخصص في‬
‫الكتابة النصية كما سبق ذكره‪ ،‬ويمدخلته هو الكائن ‪ fle‬الذي تم ربطه بالملف الفعلي في القرص‪.‬‬

‫بعد ذلك يقمنا بكتابة النص اليمرسل داخل الملف باستخدام الكائن ‪ writer‬بالطريقة التالية‪:‬‬

‫;)"‪writer.write(text + "\n‬‬

‫في النهاية قمنا بإغلق الملف باستخدام عبارة ‪ writer.close‬وهي من اﻷهمية بمكان بحيث أنه يمنع برنامج آخر‬
‫بالكتابة على هذا الملف الذي لم يتم إغلقه‪ ،‬وكذلك فإن الملف غير المغلق يمكن أن يتسبب في إهدار للموارد‪،‬‬
‫حيث أن نظام التشغيل يسمح بفتح عدد معين من الملفات في آن واحد‪ ،‬فتكرار عملية فتح الملف دون أن يكون‬
‫هناك إغلق له يمكن أن يمنع فتح ملفات جديدة أثناء تشغيل البرنامج‪.‬‬

‫ولنداء هذا اﻹجراء يجب إستدعاءه من اﻹجراء الرئيسي ‪ main‬بالطريقة التالي‪:‬‬

‫;)"‪writeToTextFile("myfile.txt", "my text‬‬

‫وييمكن تحديد المسار أو الدليل الذي ينريد كتابة الملف عليه كما فعلنا في المثال التالي لنداء هذا اﻹجراء‪ .‬وقد يقمنا‬
‫بإضافة التاريخ والوقت الذي تمت فيه كتابة الملف‪:‬‬

‫{ )‪public static void main(String[] args‬‬


‫‪// TODO code application logic here‬‬
‫;)(‪Date now = new Date‬‬
‫;‪boolean result‬‬
‫‪result = writeToTextFile("/home/motaz/java.txt",‬‬
‫;))(‪"This file has been written using Java\n" + now.toString‬‬
‫{)‪if (result‬‬
‫;)"‪System.out.print("File has been written successfully\n‬‬
‫}‬
‫{‪else‬‬
‫;)"‪System.out.print("Error has occurred while writing in the file\n‬‬
‫}‬
‫}‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫كذلك فقد يقمنا بتعريف المتغير ‪ result‬من النوع المنطقي ‪ boolean‬والذي يحتمل فقط القيم ‪ true/false‬وذلك‬
‫ﻹرجاع نتيجة العملية هل نجحت أم ل‪.‬‬

‫وقد يقمنا بفحص قيمة المتغير ‪ result‬لعرض رسالة يتفيد بأن العلمية نجحت‪ ،‬أو فشلت في حالة أن قيمته ‪.false‬‬
‫و العبارة الشرطية هي ‪if‬‬

‫)‪if (result‬‬

‫معناها أن قيمة ‪ result‬إذا كانت تحمل القيمة ‪ true‬قم بتنفيذ العبارة التالية‪ ،‬أما إذا لم تكن تحمل تلك القيمة‬
‫فقم بتنفيذ اﻹجراء بعد الكلمة ‪else‬‬

‫لتنفيذ هذا البرنامج نحتاج ﻹضافة المكتبات التالية‪ ،‬والتي تساعد أداة التطوير في إضافتها تلقائياا‪:‬‬

‫;‪import java.io.File‬‬
‫;‪import java.io.FileWriter‬‬
‫;‪import java.util.Date‬‬

‫بد ا‬
‫ل من حذف محتويات الملف في كل مرة‪ ،‬يمكن اﻹضافة فقط في النهاية بما يعرف بمصطلح ‪ append‬وهو‬
‫يعني اﻹضافة في نهاية الملف‪ .‬لعمل ذلك نقوم بتغيير طريقة تهيئة الكائن ‪ writer‬وذلك بإضافة اليمدخل ‪true‬‬
‫كالتالي‪:‬‬

‫;)‪FileWriter writer = new FileWriter(file, true‬‬

‫فعند تشغيله أكثر من مرة‪ ،‬نلحظ أن المحتويات القديمة موجودة وأن اﻹضافة تتم في النهاية‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫القراءة من ملف نصي‬
‫للقراءة من ملف ييمكن استخدام النوع ‪ FileReader‬لقراءة محتويات الملفات النصية‪ ،‬كما في المثال التالي‪:‬‬

‫)‪private static boolean readTextFile(String aFileName‬‬


‫{‬
‫{ ‪try‬‬

‫;)‪File file = new File(aFileName‬‬


‫;)‪FileReader reader = new FileReader(file‬‬

‫;]‪char buf[] = new char[10‬‬


‫;‪int numread‬‬
‫{ )‪while ((numread=reader.read(buf)) > 0‬‬

‫;)‪String text = new String(buf, 0, numread‬‬


‫;)‪System.out.print(text‬‬
‫}‬
‫;)(‪reader.close‬‬
‫‪return (true); // success‬‬

‫}‬
‫)‪catch (Exception e‬‬
‫{‬
‫;))(‪System.err.println("Error: " + e.getMessage‬‬
‫‪return (false); // fail‬‬
‫}‬

‫}‬

‫نلحظ أننا استخدمنا سلسلة من النوع ‪ char‬وهو يقوم بتخزين رمز‪ ،‬والنصوص هي مجموعة من الرموز‪.‬‬

‫;]‪char buf[] = new char[10‬‬

‫لقراءة كل محتويات الملف‪ ،‬لبد من قراءة جميع اﻷحرف‪ ،‬في كل مرة نقوم بقراءة ‪ 10‬أحرف على اﻷكثر إلى أن‬
‫تنتهي محتويات الملف‪ .‬استخدمنا العبارة التالية لقراءة جزء من الملف ثم نقوم باختبار هل وصل الملف إلى‬
‫نهايته أم ل‪:‬‬

‫{ )‪while ((numread=reader.read(buf)) > 0‬‬


‫في هذ الجزء يقوم البرنامج بقراءة محتويات الملف ثم يقوم بتخيزنها في السلسلة ‪ buf‬وبما أن حجمها هو ‪10‬‬
‫بايت فتمم قراءة ‪ 10‬رموز أو أحرف من الملف‪ ،‬ثم يتم إرجاع العدد الذي قرأه في المتغير ‪ ،numread‬وفي نهاية‬
‫الملف يمكن أن يتبقى جزء أقل من ‪ 10‬أحرف‪ ،‬فبدلا من إرجاع ‪ 10‬يقوم بإرجاع ماتبقى مثلا ‪ 5‬أحرف‪ .‬كذلك فإن‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫البرنامج في نفس السطر يقوم بمقارنة قيمة ‪ numread‬هل هي أكبر من الرقم ‪ 0‬والتي تعني أنه نجح في قراءة‬
‫بايت على اﻷقل‪ ،‬أما إذا كانت النتيجة ‪ 1-‬فهي تعني أنه لم يتبقى مقطع للقراء في الملف فيخرج تنفيذ البرنامج‬
‫من حلقة ‪.while‬‬

‫بعد ذلك قمنا بتحويل سلسلة اﻷحرف إلى مقطع لسهولة التعامل معه وكتابته في الشاشة‪:‬‬

‫;)‪String text = new String(buf, 0, numread‬‬

‫في معظم اﻷحوال فإن طول السلسة ‪ buf‬هو ‪ 10‬بايت‪ ،‬لكن ربما قرأ البرنامج عدداا أقل من اﻷحرف في نهاية‬
‫الملف‪ ،‬لذلك نقوم بنسخ الجزء الذي تمت قراءته فعلياا لذلك قمنا بتحديد المقطع المراد قرائته بواسطة اليمدخلت‬
‫‪ numread ,0‬حتى ل تتم أحرف أو كلمات إضافية من القراءة السابقة‪ ،‬ﻷننا استخدمنا المصفوفة ‪ buf‬عدة مرات‬
‫فكل مرة يكون فيه أحرف من قراءة سابقة‪.‬‬

‫نفرض أن الملف يحتوي على ‪ 25‬رمز اا‪ ،‬فتكون القراءة كالتالي‪ :‬في الدورة اﻷولى تتم قراءة ‪ 10‬رموز‪ ،‬ثم في الدورة‬
‫الثانية ‪ 10‬رموز ثم ‪ 5‬رموز‪ .‬هذه الرموز يتمثل أحرف و رمز السطر الجديد المعروف بالـ ‪ new line/line feed‬في‬
‫وندوز يتم استخدام رمزين للدللة على نهاية السطر‪ ،‬أما في نظام لينكس فيتم استخدام رمز واحد فقط وهو‬
‫‪ .new line‬قمنا بكتابة رمز السطر الجديد في المثال السابق )الكتابة في ملف نصي( وذلك باستخدام‬

‫‪\n‬‬

‫لهذا السبب استخدمنا ‪ print‬بدلا من ‪ println‬وذلك ﻷن النص المقروء من الملف يحتوي على رمز السطر الجديد‬
‫بعد نهاية كل سطر‪ ،‬أما إذا استخدمنا ‪ println‬فسوف يتم اﻹنتقال إلى سطر جديد بعد كتابة كل ‪ 10‬أحرف‬
‫فتصبح اليجمل مقطعة كالتالي‪:‬‬

‫‪This file‬‬
‫‪has been w‬‬
‫‪ritten usi‬‬
‫‪ng Java‬‬
‫‪Fr‬‬
‫‪i Aug 28 0‬‬
‫‪9:20:47 EA‬‬
‫‪T 2015‬‬

‫لكن عند استخدام ‪ print‬يظهر النص واضحاا كالتالي‪:‬‬

‫‪This file has been written using Java‬‬


‫‪Fri Aug 28 09:20:47 EAT 2015‬‬

‫ييمكن تحويل كود القراءة في هذا اﻹجراء بأن تتم قراءة محتويات الملف سطراا سطراا بدلا من قراءة عدد من‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


:String ‫الرموز ثم تحويلها إلى مقطع‬

‫ و‬InputStreamReader ‫ و‬DataInputStream ‫ و‬FileInputStream :‫هذه المرة استخدمنا الفئات‬


:‫ وذلك لقراءة سطر كامل في كل مرة كالتالي‬BuferedReader

private static boolean readTextFile(String aFileName)


{
try{
FileInputStream fstream = new FileInputStream(aFileName);

DataInputStream textReader = new DataInputStream(fstream);


InputStreamReader reader = new InputStreamReader(textReader);
BufferedReader lineReader = new BufferedReader(reader);

System.out.print("Reading " + aFileName + "\n­­­­­­­­­­­­­\n");

String line;

while ((line = lineReader.readLine()) != null){


System.out.println (line);
}
fstream.close();
return (true); // success

}
catch (Exception ex)
{
System.err.println("Error in readTextFile: " + ex.getMessage());
return (false); // fail
}

:‫ ليصبح اﻹجراء كاملا هو‬.main ‫يقمنا بنداء اﻹجراء الجديد من داخل‬

public static void main(String[] args) {


// TODO code application logic here
Date now = new Date();
boolean result;
result = writeToTextFile("/home/motaz/java.txt",
"This file has been written\n using Java\n" + now.toString());
if (result){
System.out.print("File has been written successfully\n");
}
else {
System.out.print("Error has occured while writing in the file\n");
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


readTextFile("/home/motaz/java.txt");
}

‫استعراض الملفات‬
‫ ويمكن أن يحتوي هذا المسار على ملفات ومسارات‬،‫احيان اا نحتاج ﻷن نستعرض الملفات الموجودة في مسار معين‬
.‫فرعية أخرى‬

public static void main(String[] args) {


try {

File folder = new File("/etc/");

// retrieve all files in taht directory


File files[] = folder.listFiles();

for(File afile: files)


{
System.out.print(afile.getName());

// Check if it is normal file or directory


if (afile.isDirectory()) {
System.out.println(" <DIR>");
}
else {
System.out.println("");
}
}

}
catch (Exception ex){

System.out.println("Error reading directory: " + ex.toString());


}
}

.‫ أو نقلها إلى مسار آخر‬،‫ مثل قراءة محتويتها‬،‫بعد الحصول على أسماء الملفات يمكن إدخالها في عمليات أخرى‬
.‫كذلك يمكن عمل برنامج ﻹدارة الملفات مثلا‬

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫سلسلة البيانات ‪Stream‬‬
‫توجد طرق للتعامل مع البيانات بطريقة شبيهة بالملفات مثل كتابة متسلسلة أو قراءة متسلسلة‪ ،‬لكن هذه البيانات‬
‫ل يتمثل ملفات موجودة في أي من وسائل التخزين الدائمة‪ ،‬ومثال لذلك تخزين بيانات بنفس شكل الملف في‬
‫الذاكرة‪ ،‬لغرض التخزين المؤقت أو لغرض عرضها بطريقة ما كما استخدمنا ‪ InputStreamReader‬في قراءة‬
‫ملف نصي سطراا سطر اا‪ ،‬حيث نجد أن هذه الفئة ل تتعامل مع ملف في القرص‪ ،‬إنما معلومات داخلة في شكل‬
‫سلسلة ثم تقوم بإخراجها بطريقة أسطر متسلسلة أيضاا‪.‬‬
‫مثال آخر لستخدام سلسلة البيانات ‪ streams‬هو إرسال معلومات إلى مخدم ويب عن طريق بروتوكول الـ ‪HTTP‬‬
‫وقراءة الناتج‪ ،‬فهذه الطريقة ل تتضمن تخزين ملف في وسيط‪ ،‬إنما إرسال بيانات عن طريق ‪ socket‬وقراءتها‬
‫منها‪.‬‬
‫يتم استخدام سلسلة البيانات ‪ streams‬بكثرة في لغة جافا ومكتباتها‪ ،‬وقد استخدمناها في هذا الكتاب عدة‬
‫مرات‪ ،‬منها لنقل الملفات‪ ،‬وقراءة ملف نصي بطريقة اﻷسطر‪ ،‬وفي إرسال البيانات واستقبالها من وإلى مخدمات‬
‫الويب‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫نسخ الملفات‬
‫يوجد عدد من أنواع الملفات‪ ،‬منها النصية ومنها غير النصي‪ ،‬مثل الصور وملفات الصوت والفديو‪ ،‬وغيرها من‬
‫الملفات التي تحتوي على بيانات أو حتى الملفات التنفيذية‪ .‬لكن تشترك كل هذه الملفات في أن أصغر عنصر فيها‬
‫هو البايت‪ ،‬فإذا اردنا نسخ ملف أو نقله عبر الشبكة مث ا‬
‫ل يمكننا قرائته بايت بايت ثم كتابته أثناء ذلك‪ ،‬أي قراءة‬
‫بايت من ملف مصدر ثم كتابة هذا البايت إلى الملف الجديد المنسوخ‪ ،‬ثم تكرار هذه العملية إلى نهاية الملف‬
‫المصدر‪ ،‬فإذا كان حجم الملف هو ‪ 1‬ميقابايت فإننا نقوم بتكرار هذه العملية مليون مرة‪ .‬لكن إذا قمنا بقراءة‬
‫مصفوفة حجما كيلوبايت في كل مرة ثم كتابتها في الملف الخر فإننا نحتاج لتكرار تلك العملية ألف مرة‪ ،‬وإذا‬
‫كان حجم المصفوفة ‪ 10‬كيلوبايت فنتحتاج إلى مائة مرة فقط لنقل كامل الملف‪.‬‬
‫هذه المرة سوف نستخدم الفئات‪ FileInputStream :‬لقراءة الملف و ‪ FileOutputStream‬للكتابة في الملف‬
‫الجديد‪ ،‬ونوعية الـ ‪ InputStream‬هذه متخصصة في قراءة وكتابة الملفات على شكل بايت وليس في شكل‬
‫رموز كما استخدمنا مع نوع الملفات النصية‪.‬‬

‫)‪private static void copyFiles(String sourceFileName, String targetFileName‬‬


‫{ ‪throws IOException, FileNotFoundException‬‬

‫;‪File source‬‬
‫;)‪source = new File(sourceFileName‬‬

‫;‪File target‬‬
‫;)‪target = new File(targetFileName‬‬

‫;‪FileInputStream input‬‬
‫;)‪input = new FileInputStream(source‬‬

‫;‪FileOutputStream output‬‬
‫;)‪output = new FileOutputStream(target‬‬

‫;]‪byte bucket[] = new byte[1024‬‬


‫;‪int numread‬‬
‫{)‪while ((numread = input.read(bucket)) != ­1‬‬
‫;)‪output.write(bucket, 0, numread‬‬
‫}‬
‫;)(‪output.close‬‬
‫;)(‪input.close‬‬
‫}‬

‫في هذه العبارات يقمنا بتعرف كائن ‪ source‬و ‪ target‬من نوع الفئة ‪ File‬المسؤولة عن كتابة أو قراءة الملف من‬
‫القرص‪:‬‬
‫;‪File source‬‬
‫;)‪source = new File(sourceFileName‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫;‪File target‬‬
‫;)‪target = new File(targetFileName‬‬

‫ثم في العبارات التي تليها قمنا بتعريف الكائنات ‪ input‬و ‪ output‬من نوع ‪ FileInputStream‬و‬
‫‪ FileOutputStream‬على التوالي‪ ،‬وهي مسؤولة عن قراءة وكتابة مصفوفة من نوع بايت‪:‬‬

‫;‪FileInputStream input‬‬
‫;)‪input = new FileInputStream(source‬‬

‫;‪FileOutputStream output‬‬
‫;)‪output = new FileOutputStream(target‬‬

‫بعد ذلك قمنا بتعريف مصفوفة البايت بإسم ‪ packet‬حجمها كيلو بايت‪ ،‬ثم أدخلناها في حلقة قراءة من المصدر‬
‫وكتابة في الملف المراد نسخة إلى نهاية القراءة من المصدر‪ ،‬ونتعرف على نهاية القراءة عندما إرجاع القيمة ‪-1‬‬
‫لعدد البايت التي تمت قرائتها‪:‬‬

‫;]‪byte bucket[] = new byte[1024‬‬


‫;‪int numread‬‬
‫{)‪while ((numread = input.read(bucket)) != ­1‬‬
‫;)‪output.write(bucket, 0, numread‬‬
‫}‬

‫نلحظ أننا لم نقم بكتابة كامل المصفوفة في الملف الهدف كالتالي‪:‬‬


‫;)‪output.write(bucket‬‬

‫حيث أن هذه العبارة سوف تقوم بكتابة كامل المصفوفة )كيلوبايت( في الملف المنسوخ‪ ،‬فإذا كان حجم الملف هو‬
‫كيلوبايت ونصف الكيلو فإن الكتابة بتلك الطريقة سوف تكتب ‪ 2‬كيلو في الملف الهدف‪ ،‬وسوف يحتوى الكيلو‬
‫الثاني على زيادة هي عبارة عن باقي محتويات القراءة اﻷولى‪ .‬لذلك قمنا بكتابة الجزء المقروء فقط من‬
‫المصفوفة‪ ،‬فلو تم قراءة ‪ 100‬بايت في أي دورة تتم كتابة ‪ 100‬بايت فقط‪ ،‬وإذا تمت قراءة كيلو بايت كامل تتم‬
‫كتابة كيلوبايت‪:‬‬
‫;)‪output.write(bucket, 0, numread‬‬

‫واليمدخل )‪ (0‬يعني الكتابة من بداية المصفوفة‪ ،‬و ‪ numread‬هو المكان الذي سوف تتوقف الكتابة قبله‪ ،‬أي‬
‫الموقع ‪ 1023‬في حال أن ‪ numread‬بها القيمة ‪ ،1024‬و المصفوفة ذات الـ ‪ 1024‬بايت تبدأ في البايت ‪ 0‬وتنتهي‬
‫عن البايت ‪.1023‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


:‫بعد ذلك نقوم بإغلق كافة الملفين‬

output.close();
input.close();

‫و الناتج هو ملف منسوخ مماثل في‬،‫بهذه الطريقة يمكن نسخ أي نوع من الملفات بغض النظر عن محتوياتها‬
.‫المحتويات للملف اﻷصلي‬
:‫نقوم بنداء إجراء نسخ الملفات كالتالي‬

copyFiles("/home/motaz/fish.jpg", "/home/motaz/fish­copy.jpg");

output ‫ و‬input ‫ وربط الملف مباشرة أثناء تهيئة‬source, target ‫يمكن الستغناء عن كائنات التعامل مع الملف‬
:‫ليصبح البرنامج مختصراا كالتالي‬

private static void copyFiles(String sourceFileName, String targetFileName)


throws IOException, FileNotFoundException {

FileInputStream input;
input = new FileInputStream(sourceFileName);

FileOutputStream output;
output = new FileOutputStream(targetFileName);

byte bucket[] = new byte[1024];


int num;
while ((num = input.read(bucket)) != ­1){
output.write(bucket, 0, num);
}
output.close();
input.close();
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫الخصائص ‪Properties‬‬
‫نقصد بها تخزين وقراءة المعلومات في شكل إسم المعلومة مع قيمتها كالتالي‪:‬‬
‫‪name=value‬‬
‫مثلا‪:‬‬
‫‪myname=Mohamed Ali‬‬
‫‪age=30‬‬
‫‪address=Sudan,Khartoum‬‬
‫ويتم اﻹستفادة من هذه التقنية باستخدامها في عمل إعدادات للبرامج‪ ،‬مثلا البرنامج عندما يعمل يقوم بالقراءة‬
‫من ملف خصائص أو ملف إعدادات تخبره بمعلومات عن البيئة التي حوله‪ ،‬مثلا عن اسم مخدم قاعدة البيانات‪،‬‬
‫وعن اسم الدخول وكلمة المرور‪ ،‬وغيرها من المعلومات التي يحتاج إليها البرنامج حتى يعمل‪ ،‬وإذا يقمنا بإدخال‬
‫هذه المعلومات ) مثل اسم مخدم قاعدة البيانات( فإذا اردنا أن يعمل البرنامج في بيئة مختلفة وقاعدة بيانات‬
‫أخرى ل نستطيع‪ ،‬إل إذا قمنا بتعديل البرنامج ثم إعادة ترجمته‪ ،‬وهذه طريقة غير صحيحة يتسمى بالـ ‪hard-‬‬
‫‪ coding‬وهي أن تكون البيانات البيئية التشغيلية للبرنامج توجد داخله‪ ،‬الحل اﻷمثل ان تكون خارجه في ملف‬
‫إعدادات يمكن تغييرها بكل سهولة ويسر دون إعادة ترجمة البرنامج‪ ،‬واحياناا دون الحاجة ﻹغلق البرنامج‪.‬‬
‫في المثال التالي قمنا بتعريف كائن من نوع فئة الخصائص ‪ Properties‬وقمنا بتخزين قيم فيها ثم قراءة تلك‬
‫القيم‪:‬‬
‫‪// Writing‬‬
‫;)(‪Properties myproperty = new Properties‬‬
‫;)"‪myproperty.setProperty("Name", "Mohammed Ali‬‬
‫;)"‪myproperty.setProperty("Age", "30‬‬
‫;)"‪myproperty.setProperty("Age", "32‬‬

‫‪// Reading‬‬
‫;))"‪System.out.println(myproperty.getProperty("Name‬‬
‫;))"‪System.out.println(myproperty.getProperty("Age‬‬
‫;))(‪System.out.println(myproperty.toString‬‬

‫فتكون المخرجات كالتالي‪:‬‬


‫‪Mohammed Ali‬‬
‫‪32‬‬
‫}‪{Name=Mohammed Ali, Age=32‬‬

‫نكتب أولا إسم القيمة مثل ‪ Name‬ثم قيمتها ‪ Mohammed Ali‬باستخدام الدالة ‪ setProperty‬وينلحظ أن‬
‫هناك فرق في اﻹسم بين الحرف الكبير الصغير ‪ ،case sensitive‬كذلك أننا يقمنا بوضع القيمة ‪ 30‬تحت اﻹسم‬
‫‪ Age‬ثم قمنا بإعادة وضع القيمة ‪ ،32‬في هذه الحالة يتم تغيير قيمة ‪ Age‬بالقيمة اﻷخيرة ول يتم تكرار اﻷسماء‬
‫وهذه ميزة مهمة حيث ل يتم وضع متغيرين بنفس اﻹسم لهما قيم مختلفة‪.‬‬
‫بعد ذلك قمنا بقراءة القيم باستخدام ‪ .getProperty‬كذلك يمكن إضافة قيمة افتراضية في حال عدم وجود‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


:‫ مثلا‬،‫القيمة‬
System.out.println(myproperty.getProperty("Adress", "Sudan,Khartoum"));
‫ أما إذا كانت موجودة فيتم‬،‫ غير موجودة أي لم يتم إدخالها فيتم وضع قيما بديلة لها‬Address ‫فإذا كانت القيمة‬
:‫تجاهل القيمة اﻹفتراضية كالتالي‬
System.out.println(myproperty.getProperty("Age", "20"));
‫ هذه الميزة ييمكن الستفادة منها مع ملف اﻹعدادات لتعيين قيم بيئية افتراضية في حال أنه‬،32 ‫حيث يتم كتابة‬
.‫ل توجد إعدادات تم تخصيصها‬
.‫ تقوم بإرجاع كافة القيم في كائن الخصائص‬myproperty.toString ‫العبارة‬

‫ ولعمل هذا نقوم باستخدام ملف من نوع‬،‫ينقص كائن الخصائص هذا التخزين في ملف حتى ل تضيع معلوماته‬
:‫ بإضافة الكود التالي‬FileOutputStream ‫ او‬FileWriter

FileWriter writer = new FileWriter("/home/motaz/testing/config.ini");


myproperty.store(writer, "Configuration");
writer.close();
:‫فيصبح لدينا ملف خارجي بهذه المحتويات‬
#Configuration
#Fri Aug 26 16:00:41 EAT 2016
Name=Mohammed Ali
Age=30

‫وفي المرة القادمة لبد من قراءة الملف بد ا‬


‫ وذلك بإضافة الكود التالي لبداية‬،‫ل من كتابة ملف جديد كل مرة‬
:File ‫ لذلك استخدمنا الفئة‬،‫ لكن أولا يجب التأكد من أن الملف موجود في القرص‬،‫استخدام كائن الخصائص‬
// Read from file
File file = new File("/home/motaz/testing/config.ini");
Properties myproperty = new Properties();
if (file.exists()){
FileReader reader = new FileReader(file);
myproperty.load(reader);
reader.close();
}

:‫وهذا هو الكود كاملا‬


public static void main(String[] args)
throws FileNotFoundException, IOException {

// Read from file


File file = new File("/home/motaz/testing/config.ini");
Properties myproperty = new Properties();
if (file.exists()){
FileReader reader = new FileReader(file);

Code.sd ‫كود لبرمجيات الكبيوتر‬


myproperty.load(reader);
reader.close();
}

// Writing
myproperty.setProperty("Name", "Mohammed Ali");
myproperty.setProperty("Age", "30");
myproperty.setProperty("Address", "Sudan,Khartoum");

// Reading
System.out.println(myproperty.getProperty("Name"));
System.out.println(myproperty.getProperty("Age"));
System.out.println(myproperty.getProperty("Address", "Sudan"));

FileWriter writer = new FileWriter(file);


myproperty.store(writer, "Configuration");
writer.close();
}

‫في الغالب فإننا نحتاج فقط قراءة القيم الموجودة في ملف اﻹعدادات حيث أن الكتابة غالباا تتم خارجياا بواسطة‬
‫ مباشرة في الملف باستخدام‬name=value ‫ حيث يقوم بكتابة القيم في شكل‬،‫المبرمج أو المسؤول عن النظام‬
‫ وهذا إجراء قمنا بكتابته لقراءة أي قيمة من‬.‫ ليقوم برنامج جافا بقراءة تلك القيم واستخدامها‬،‫أي محرر نصوص‬
:‫أي ملف‬

private static String readConfig(String name, String filename)


throws IOException {

// Read from file


File file = new File(filename);
Properties myproperty = new Properties();
if (file.exists()){
FileReader reader = new FileReader(file);
myproperty.load(reader);
reader.close();
}
String avalue = myproperty.getProperty(name);
return avalue;
}

:‫ويمكن نداءه بالطريقة التالية‬

String avalue = readConfig("Address", "/home/motaz/testing/config.ini");


System.out.println(avalue);

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫المصفوفات ‪arrays‬‬
‫لتعريف مصفوفة في لغة جافا نضيف إلى السم أو إلى نوع المتغير اﻷقواس المربع ] [ بدون مسافة داخلها بعدة‬
‫أشكال وهي‪:‬‬

‫;‪int[] arr‬‬
‫;‪int []arr2‬‬
‫;][‪int arr3‬‬

‫والطرق الثلث صحيحة لتعريف مصفوفة من النوع ‪.int‬‬


‫بعد ذلك تتم تهيئة المصفوفة بالطول المناسب‪:‬‬

‫;]‪arr = new int[5‬‬

‫بهذا نكون قد حجزنا خمس خانات في المصفوفة تبدأ من ‪ 0‬وتنتهي بـ ‪ ،4‬ويمكن وضع قيم فيها بالطريقة التالية‪:‬‬

‫]‪arr[0‬‬ ‫=‬ ‫;‪10‬‬


‫]‪arr[1‬‬ ‫=‬ ‫;‪20‬‬
‫]‪arr[2‬‬ ‫=‬ ‫;‪6‬‬
‫]‪arr[3‬‬ ‫=‬ ‫;‪3‬‬
‫]‪arr[4‬‬ ‫=‬ ‫;‪9‬‬

‫ثم طباعة قيم المصفوفة كاملة باستخدام حلقة ‪ for‬كالتالي‪:‬‬

‫{ )‪for (int i=0; i < arr.length; i++‬‬


‫;)]‪System.out.println(arr[i‬‬
‫}‬

‫وتوجد طريقة مختصرة لحلقة ‪ for‬بالنسبة للمصفوفات والسلسل عموماا في لغة جافا‪ ،‬حيث يمكن تحويلها إلى‬
‫الطريقة التالية‪:‬‬

‫{ )‪for (int x: arr‬‬


‫;)‪System.out.println(x‬‬
‫}‬

‫حيث تقوم الحلقة باسناد قيم المصفوفة بالتتالي للمتغير ‪ x‬لستخدامه لحقاا داخل الحلقة إلى أن تتنهي عناصرها‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫السلسل ‪ArrayList‬‬
‫طريقة المصفوفة السابقة يتستخدم عندما نعلم الطول أثناء كتابة البرنامج أو أثناء التشغيل‪ ،‬لكن احياناا ل يمكن‬
‫معرفة الطول المطلوب إل عند اﻹنتهاء من إدخال العناصر‪ ،‬مثلا إذا طلبنا من المستخدم أن يقوم بإدخال أسماء‪،‬‬
‫ثم في آخر إسم يقوم بضغط مفتاح اﻹدخال دون الكتابة ليعلم البرنامج بإنتهاء اﻹدخال‪ ،‬في هذه الحالة ل يمكن‬
‫معرفة عدد اﻷسماء المراد إدخالها‪ ،‬وهنا ل يصلح استخدام المصفوفة‪ ،‬لكن نستخدم السلسلة ‪ ArrayList‬كما في‬
‫المثال التالي‪:‬‬

‫‪// Declare array list‬‬


‫;‪ArrayList<String> nameList‬‬

‫‪// Intialize arraylist‬‬


‫;)(><‪nameList = new ArrayList‬‬

‫;"" = ‪String name‬‬

‫‪// Read user input‬‬


‫;)"‪System.out.println("Please input names, and press enter‬‬
‫;)‪Scanner sc = new Scanner(System.in‬‬
‫{ ‪do‬‬
‫;)(‪name = sc.nextLine‬‬

‫‪// Add name to list‬‬


‫;)‪nameList.add(name‬‬
‫;))(‪} while (!name.isEmpty‬‬

‫‪// display list‬‬


‫{)‪for (String aname: nameList‬‬
‫;)‪System.out.println(aname‬‬
‫}‬

‫في هذا المثال قمنا باﻹعلن عن السلسلة بالطريقة التالية‪:‬‬


‫;‪ArrayList<String> nameList‬‬

‫ونوع المتغير أو العنصر الواحد في السلسلة هو مقطع ‪ ،String‬وتتم تهيئتها بالطريقة التالية‪:‬‬
‫;)(><‪nameList = new ArrayList‬‬

‫قديم اا في النسخة السادسة من الجافا كان لبد من كتابة نوع العنصر مرة أخرى كالتالي‪:‬‬
‫;)(>‪nameList = new ArrayList<String‬‬

‫لكن منذ جافا ‪ 7‬تم اختصار نوع العنصر بما ييسمى بعلمة الماسة ‪<> Diamond‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫يمكن تحويل نسخة البرنامج إلى جافا ‪ 6‬أو ‪ 5‬بواسطة خصائص البرنامج ‪ properties‬ثم تغييرها كالتالي‪:‬‬

‫فنجد أن المترجم أعطى خطأ أمام التهيئة بواسطة >< وعند تحويلها إلى >‪ <String‬يعتبرها صحيحة‪.‬‬
‫طريقة تحويل مصدر برنامج جافا إلى ينسخة أقدم من جافا يتم استخدامها احياناا حينما نريد تشغيل برنامج جافا‬
‫في آلة افتراضية قديمة في مخدم مثلا‪ .‬حيث أن بعض المخدمات يصعب تحديثها إلى ينسخة جديدة من جافا‪.‬‬
‫عند تشغيل البرنامج لبد من وضع المؤشر في الجزء اﻷسفل من الشاشة حتى نتمكن من إدخال اﻷسماء بالطريقة‬
‫التالية‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬
‫تعريف الكائنات والذاكرة‬
‫من اﻷمثلة السابقة ينلحظ أننا استخدمنا البرمجة الكائنية في قراءة وكتابة الملفات والتاريخ‪ .‬وينلحظ أن تعريف‬
‫الكائن وتهيته يمكن أن تكون في عبارة واحدة‪ ،‬مثلا لتعريف التاريخ ثم تهيئته بالوقت الحالي استخدمنا‪:‬‬

‫;)(‪Date today = new Date‬‬

‫وكان ييمكن فصل التعريف للكائن الجديد من تهيئته بالطريقة التالية‪:‬‬

‫;‪Date today‬‬
‫;)(‪today = new Date‬‬

‫هذه المرة في العبارة اﻷولى يقمنا بتعريف الكائن ‪ today‬من نوع الفئة ‪ .Date‬لكن إلى الن ل ييمكننا استخدام‬
‫الكائن ‪ today‬فلم يتم حجز موقع له في الذاكرة‪.‬‬

‫أما في العبارة الثانية فقد يقمنا بحجز موقع له في الذاكرة بإستخدام الكلمة ‪ new‬ثم تهيئة اللكائن بإستخدام‬
‫اﻹجراء‬

‫;)(‪Date‬‬
‫والذي بدوره يقوم بقراءة التاريخ والوقت الحالي ﻹسناده للكائن الجديد ‪ .today‬وهذا اﻹجراء ييسمى في‬
‫البرمجة الكائنية ‪.constructor‬‬

‫في هذا المثال ‪ Date‬هي عبارة عن فئة لكائن أو يتسمى ‪ class‬في البرمجة الكائنية‪ .‬و المتغير ‪ today‬ييسمى كائن‬
‫‪ object‬أو ‪ instance‬وييمكن تعريف أكثر من كائن ‪ instance‬من نفس الفئة لستخدامها‪ .‬وتعريف كائن جديد من‬
‫فئة ما وتهيئتها يتسمى ‪ object instantiation‬في البرمجة الكائنية‪.‬‬

‫بعد الفراغ من استخدام الكائن يمكننا تحريره من الذاكرة وذلك باستخدام الدالة التالية‪:‬‬

‫;‪today = null‬‬

‫توجد في لغة جافا ما ييعرف بال ‪ garbage collector‬وهي آلية لحذف الكائنات الغير مستخدمة من الذاكرة‬
‫تلقائي اا عندما ينتهي تنفيذ اﻹجراء‪ .‬يتم فقط حذف الكائنات المعرفة في نطاق هذا اﻹجراء‪ .‬في معظم اﻷحيان ل‬
‫نحتاج لستخدام هذه العبارة‪ ،‬فإذا تم اﻹنتهاء من استخدام المتغير الذي يؤشر لهذا الكائن يتم تحريره تلقائياا‪.‬‬

‫مفهوم – غير مستخدم‪ -‬يعني أنه ل يوجد مؤشر له من المتغيرات‪ ،‬حيث يمكن أن يكون لكائن ما عدد من‬
‫المؤشرات تؤشر له‪ ،‬فعندما تنتهي جميع هذه المؤشرات ويصبح عدد المتغيرات التي تؤشر لهذا الكائن في الذاكرة‬
‫صفراا يقوم الـ ‪ garbage collector‬بحذفه من الذاكرة بعد مدة معينة‪ .‬أما لغات البرمجة اﻷخرى مثل سي‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫وأوبجكت باسكال فعند استخدامها لبد من تحرير الكائنات يدوياا في معظم الحالت‪.‬‬

‫نهاية المتغير يكون بنهاية تنفيذ الحيز الموجود فيه وهو المحاط بالقوسين }{‬

‫نأخذ هذا المثال لشرح مفهوم حيز أو نطاق تعريف المتغير‪:‬‬

‫‪1‬‬ ‫{ )‪public static void main(String[] args‬‬


‫‪2‬‬
‫‪3‬‬ ‫;"‪String yourName = "Mohammed‬‬
‫‪4‬‬ ‫{‬
‫‪5‬‬ ‫;"‪String myName = "Motaz‬‬
‫‪6‬‬ ‫;)‪System.out.println(myName‬‬
‫‪7‬‬ ‫}‬
‫‪8‬‬ ‫;)‪System.out.println(yourName‬‬
‫‪9‬‬
‫‪10‬‬ ‫}‬

‫نجد أن المتغير ‪ yourName‬معرف داخل اﻹجراء ‪ main‬لذلك ل ينتهي إل بانتهاء هذا اﻹجراء‪ ،‬أي عند السطر‬
‫رقم ‪.10‬‬

‫أما المتغير ‪ myName‬والمعرف في نطاق أضيق‪ ،‬فينتهي عند السطر رقم ‪ ،7‬فإذا أردنا أن نجعله ذو عمر أطول‬
‫يمكن تعريفه خارج هذا النطاق الضيق‪:‬‬

‫‪1‬‬ ‫{ )‪public static void main(String[] args‬‬


‫‪2‬‬
‫‪3‬‬ ‫;"‪String yourName = "Mohammed‬‬
‫‪4‬‬ ‫;‪String myName‬‬
‫‪5‬‬ ‫{‬
‫‪6‬‬ ‫;"‪myName = "Motaz‬‬
‫‪7‬‬ ‫;)‪System.out.println(myName‬‬
‫‪8‬‬ ‫}‬
‫‪9‬‬ ‫;)‪System.out.println(yourName‬‬
‫‪10‬‬
‫‪11‬‬ ‫;)"‪readTextFile("/home/motaz/java.txt‬‬
‫‪12‬‬ ‫}‬

‫بهذه الطريقة يصبح عمر المتغير ‪ myName‬مرتبط بنهاية اﻹجراء ‪ ،main‬ونلحظ أننا قمنا فقط بنقل التعريف‬
‫إلى الخارج‪ ،‬لكن التهيئة فمازالت داخل ذلك الحيز‪ ،‬لكن هذا لم يؤثر على قيمته أو نطاق تعريفه‪.‬‬

‫يمكن تهيئة كائن جديد بواسطة إسناد مؤشر كائن قديم له‪ ،‬في هذه الحالة يكون كل المتغيرين يؤشران لنفس‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫الكائن في الذاكرة‪:‬‬

‫;‪Date today‬‬
‫;‪Date today2‬‬
‫;)(‪today = new Date‬‬
‫;‪today2 = today‬‬
‫;‪today = null‬‬
‫;)"‪System.out.print("Today is: " + today2.toString() + "\n‬‬
‫نلحظ أننا لم نقم بتهيئة المتغير ‪ today2‬لكن بدلا من ذلك جعلناه يؤشر لنفس الكائن ‪ today‬الذي تمت تهيئته‬
‫من قبل‪.‬‬

‫بعد ذلك يقمنا بتحرير المتغير ‪ ،today‬إل أن ذلك لم يؤثر على الكائن‪ ،‬حيث أن الكائن مايزال مرتبط بالمتغير‬
‫‪ .today2‬ول تقوم آلية ‪ garage collector‬بتحرير الكائن من الذاكرة إل عندما تصبح عدد المتغيرات التي تؤشر‬
‫له صفراا‪ .‬فإذا يقمنا بتحرير المتغير ‪ today2‬أيضاا تحدث مشكلة عند تنفيذ السطر اﻷخير‪ ،‬وذلك ﻷن الكائن تم‬
‫تحريره من الذاكرة ومحاولة الوصول إليه بالقراءة أو الكتابة ينتج عنها خطأ‪.‬‬

‫ولمعرفة ماهو الخطأ الذي ينتج يقمنا بإحاطة الكود بعبارة ‪ try catch‬كما في المثال التالي‪:‬‬

‫{ ‪try‬‬
‫;‪Date today‬‬
‫;‪Date today2‬‬
‫;)(‪today = new Date‬‬
‫;‪today2 = today‬‬
‫;‪today = null‬‬
‫;‪today2 = null‬‬
‫;)"‪System.out.print("Today is: " + today2.toString() + "\n‬‬
‫{ )‪} catch (Exception e‬‬
‫;)"‪System.out.print("Error: " + e.toString() + "\n‬‬
‫}‬
‫والخطأ الذي تحصلنا عليه هو‪:‬‬

‫‪java.lang.NullPointerException‬‬
‫ملحظة‪:‬‬

‫في لغة جافا ياصطلح على تسمية الفئات ‪ classes‬بطريقة أن يكون الحرف اﻷول كبير ‪ capital‬مثل ‪Date,‬‬
‫‪ ,String‬حتى الفئات التي يقوم المبرمج بكتابتها‪ .‬أما الكائنات ‪ objects/instances‬فتبدأ بحرف صغير وذلك‬
‫للتفرقة بين الفئة والكائن‪ ،‬مثل ‪.today, today2, myName‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫برنامج اختيار الملف‬
‫هذه المرة ينريد عمل برنامج ذو واجهة رسومية يسمح لنا بإختيار الملف بالماوس‪ ،‬ثم عرض محتوياته في صندوق‬
‫نصي‪.‬‬

‫لعمل هذا البرنامج نفتح مشروع جديد بواسطة ‪ .Java/Java Application‬نسمي هذا المشروع ‪openfle‬‬

‫ينضيف ‪ JFrame Form‬نسميه ‪ MainForm‬ونضع فيه المكونات التالية‪:‬‬

‫‪Button, Label, Text Area‬‬

‫كما في الشكل التالي‪:‬‬

‫بعد ذلك نكتب هذا الكود في اﻹجراء ‪ main‬في ملف البرنامج الرئيسي ‪ Openfle.java‬ﻹظهار الفورم فور‬
‫تشغيل البرنامج‪:‬‬

‫{ )‪public static void main(String[] args‬‬

‫;)(‪MainForm form = new MainForm‬‬


‫;)‪form.setVisible(true‬‬
‫}‬
‫نقوم بنسخ اﻹجراء ‪ readTextFile‬من البرنامج السابق إلى كود البرنامج الحالي‪ ،‬ونعدله قلي ا‬
‫ل‪ ،‬نضيف له مدخل‬
‫جديد من نوع ‪ JTextArea‬وذلك لكتابة محتويات الملف في هذا المربع النصي بدلا من شاشة سطر اﻷوامر‬
‫‪ .Console‬وهذا هو اﻹجراء المعدل‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


private static boolean readTextFile(String aFileName, JTextArea textArea)
{
try {
FileInputStream fstream = new FileInputStream(aFileName);

DataInputStream textReader = new DataInputStream(fstream);

InputStreamReader isr = new InputStreamReader(textReader);


BufferedReader lineReader = new BufferedReader(isr);

String line;
textArea.setText("");

while ((line = lineReader.readLine()) != null){


textArea.append(line + "\n");
}

fstream.close();
return (true); // success

}
catch (Exception e)
{
textArea.append("Error in readTextFile: " + e.getMessage() + "\n");
return (false); // fail
}
:‫ في الزر نكتب الكود التالي‬ActionPerformed ‫وفي الحدث‬

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

final JFileChooser fc = new JFileChooser();


int result = fc.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
jLabel1.setText(fc.getSelectedFile().toString());
readTextFile(fc.getSelectedFile().toString(), jTextArea1);
}
}
:‫وقد يقمنا بتعريف كائن اختيار الملف في السطر التالي‬

final JFileChooser fc = new JFileChooser();

‫ هل قام المستخدم باختيار‬:‫ ويقوم بإرجاع النتيجة‬.‫ثم قمنا بإظهاره ليختار المستخدم الملف في السطر التالي‬
:‫ملف أم ضغط إلغاء‬

int result = fc.showOpenDialog(null);

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫فإذا قام باختيار ملف نقوم بكتابة اسمه في العنوان ‪ jLabel1‬ثم نظهر محتوياته داخل مربع النص‪:‬‬

‫{ )‪if (result == JFileChooser.APPROVE_OPTION‬‬


‫;))(‪jLabel1.setText(fc.getSelectedFile().toString‬‬
‫;)‪readTextFile(fc.getSelectedFile().toString(), jTextArea1‬‬
‫}‬
‫وعند تشغيل البرنامج يظهر لنا بهذا الشكل بعد إختيار الملف‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫كتابة فئة كائن جديد ‪New Class‬‬
‫لغة جافا تعتمد فقط نموذج البرمجة الكائنية ‪ ،Object Oriented paradigm‬وقد مر علينا في اﻷمثلة السابقة‬
‫استخدام عدد من الكائنات‪ ،‬سوااء كانت لقراءة التاريخ أو للتعامل مع الملفات أو الكائنات الرسومية مثل ‪Label‬‬
‫والـ ‪ Text Area‬والفورم ‪ .JFrameForm‬لكن حتى تصبح البرمجة الكائنية أوضح لبد من إنشاء فئات ‪classes‬‬
‫جديدة بواسطة المبرمج لتعريف كائنات منها‪.‬‬

‫في هذا المثال سوف نقوم بإضافة فئة ‪ class‬جديدة يندخل لها جملة نصية ﻹرجاع الكلمة اﻷولى واﻷخيرة من‬
‫الجملة‪.‬‬

‫قمنا بفتح برنامج جديد من نوع ‪ ،Java Application‬و أسميناه ‪،newclass‬‬

‫بعد ذلك أضفنا ‪ MainForm‬من نوع ‪JFrameForm‬‬

‫ثم يقمنا بإدراج ‪ Text Field‬و ‪ Button‬و ‪ Text Area‬بهذا الشكل في الفورم الرئيسي‪:‬‬

‫ول ننسى تعريف الفورم وتهيئته ﻹظهاره مع تشغيل البرنامج في اﻹجراء الرئيسي في الملف ‪:Newclass.java‬‬

‫{ )‪public static void main(String[] args‬‬

‫;)(‪MainForm form = new MainForm‬‬


‫;)‪form.setVisible(true‬‬
‫}‬
‫بعد ذلك قمنا بإضافة ‪ class‬جديدة وذلك بإختيار ‪ Source Packages/new class‬بالزر اليمين ثم اختيار‬
‫‪ New/Java Class‬من القائمة‪ .‬ثم نسمي الفئة الجديدة ‪ Sentence‬فيظهر لنا هذا الكود‪:‬‬

‫*‪/‬‬
‫‪* To change this template, choose Tools | Templates‬‬
‫‪* and open the template in the editor.‬‬
‫‪*/‬‬
‫;‪package newclass‬‬

‫*‪/‬‬
‫*‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫‪* @author motaz‬‬
‫‪*/‬‬
‫{ ‪public class Sentence‬‬

‫}‬
‫وفي داخل كود الفئة ‪-‬بين القوسين المعكوفين }{ ‪ -‬قمنا بإضافة متغير مقطعي اسميناه ‪ mySentence‬لنحفظ‬
‫فيه الجملة التي يتم إرسالها لتكون محتفظة بقيمة الجملة طوال فترة حياة الكائن‪.‬‬

‫ثم أضفنا اﻹجراء الذي ييستخدم في تهيئة الكائن‪ ،‬ولبد أن يكون اسمه مطابق ﻹسم الفئة‪:‬‬

‫;‪String mySentence‬‬

‫{)‪public Sentence (String atext‬‬


‫;)(‪super‬‬
‫;‪mySentence = atext‬‬
‫}‬

‫نلحظ أنه في هذا اﻹجراء تم إسناد قيمة اليمدخل ‪ atext‬إلى المتغير ‪ mySentence‬اليمعرف على نطاق الكائن‪.‬‬
‫حيث أن المتغير ‪ atext‬نطاقه فقط اﻹجراء ‪ Sentence‬وعند اﻹنتهاء من نداء هذا اﻹجراء يصبح غير معروف‪.‬‬
‫لذلك إحتفظنا بالجملة اليمدخلة في متغير في نطاق أعلى لتكون حياته أطول‪ ،‬حيث ييمكن استخدامه مادام الكائن‬
‫لم يتم حذفه من الذاكرة‪.‬‬

‫بعد ذلك يقمنا بإضافة إجراء جديد في نفس فئة الكائن اسمه ‪ getFirst‬وهو يقوم بإرجاع الكلمة اﻷولى من‬
‫الجملة‪:‬‬

‫{)(‪public String getFirst‬‬


‫;‪String first‬‬
‫;‪int firstSpaceIndex‬‬
‫;)" "(‪firstSpaceIndex = mySentence.indexOf‬‬

‫)‪if (firstSpaceIndex == ­1‬‬


‫;‪first = mySentence‬‬
‫‪else‬‬
‫;)‪first = mySentence.substring(0, firstSpaceIndex‬‬

‫;)‪return (first‬‬
‫}‬
‫نلحظ اننا استخدمنا اﻹجراء ‪ indexOf‬في المتغير أو الكائن المقطعي ‪ mySentence‬ويقمنا بإرسال مقطع‬
‫يحتوي على مسافة‪ .‬وهذا اﻹجراء أو الدالة مفترض به في هذه الحالة أن يقوم بإرجاع موقع أول مسافة في‬
‫الجملة‪ ،‬وبهذه الطريقة نعرف الكلمة اﻷولى‪ ،‬حيث أنها تقع بين الحرف اﻷول وأول مسافة‪.‬‬

‫أما إذا لم تكن يهناك مسافة موجودة في الجملة فتكون نتيجة الدالة ‪ indexOf‬يساوي ‪ 1-‬وهذا يعني أن الجملة‬
‫تتكون من كلمة واحدة فقط‪ ،‬في هذه الحالة نقوم بإرجاع الجملة كاملة )الجملة = كلمة واحدة(‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ والتي ينعطيها بداية ونهاية‬substring ‫وإذا يوجدت المسافة فعندها نقوم بنسخ مقطع من الجملة بإستخدام الدالة‬
frst ‫ ونتيجة النسخ ترجع في المتغير أو الكائن المقطعي‬.‫المقطع اليمراد نسخه‬

‫ وهو يقوم بإرجاع آخر كلمة في‬getLast ‫ هو‬Sentence ‫الدالة أو اﻹجراء الخر الذي يقمنا بإضافته في الفئة‬
:‫الجملة‬

public String getLast(){


String last;
int lastSpaceIndex;
lastSpaceIndex = mySentence.lastIndexOf(" ");

if (lastSpaceIndex == ­1){
last = mySentence;
}
else {
last = mySentence.substring(lastSpaceIndex + 1, mySentence.length());
}
return (last);
}
‫( إلى‬lastIndexOf ) ‫ ويختلف في أنه يقوم بالنسخة من آخر مسافة موجودة في الجملة‬،‫وهو مشابه للدالة اﻷخرى‬
mySentence.length ‫نهاية الجملة‬

:‫والكود الكامل لهذه الفئة هو‬

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package newclass;

/*
*
* @author motaz
*/
public class Sentence {

String mySentence;

public Sentence (String atext){

super();
mySentence = atext;
}

public String getFirst(){

String first;
int firstSpaceIndex;

Code.sd ‫كود لبرمجيات الكبيوتر‬


firstSpaceIndex = mySentence.indexOf(" ");

if (firstSpaceIndex == ­1){
first = mySentence;
}
else {
first = mySentence.substring(0, firstSpaceIndex);
}

return (first);
}

public String getLast(){

String last;
int lastSpaceIndex;
lastSpaceIndex = mySentence.lastIndexOf(" ");

if (lastSpaceIndex == ­1){
last = mySentence;
}
else {
last = mySentence.substring(lastSpaceIndex + 1, mySentence.length());
}

return (last);
}
}
‫ واستقبلنا‬،‫ قمنا بتعريف وتهيئة ثم استخدام هذا الكائن‬MainForm.java ‫في كود الفورم الرئيسي للبرنامج‬
:‫ وهذا هو الكود الذي يتم تنفيذه عند الضغط على الزر‬.Text Field ‫الجملة في مربع النص‬

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

Sentence mySent = null;


mySent = new Sentence(jTextField1.getText());

jTextArea1.append("First: " + mySent.getFirst() + "\n");


jTextArea1.append("Last: " + mySent.getLast() + "\n");
}
:‫قمنا بإنشاء كائن جديد وتهيئته في هذا السطر‬

mySent = new Sentence(jTextField1.getText());

‫ الموجود في‬getText ‫ بواسطة اﻹجراء‬jTextField1 ‫واليجملة اليمدخلة أثناء التهيئة تحصلنا عليها من مربع النص‬
.‫هذا الكائن‬

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫المتغيرات واﻹجراءات الساكنة )‪(static‬‬
‫فيما سبق لنا من تعامل مع الفئات وجدنا أنه لبد من تعريف كائن من نوع الفئة قبل التعامل معها‪ ،‬فمثلا ل نستطيع‬
‫الوصول ﻹجراء الفئة بدون أن تصبح كائن‪ .‬فنجد أن المثال التالي غير صحيح‪:‬‬

‫;)"‪jTextArea1.append("First: " + Sentence.getFirst() + "\n‬‬

‫لكن ييمكن استخدام إجراءات في فئات دون تعريف كائنات منها بتحويلها إلى إجراءات ساكنة‬
‫‪.static methods‬‬
‫وهذا مثال لطريقة تعريف متغيرات وإجراءات ساكنة في لغة جافا‪:‬‬

‫{ ‪public static class MyClass‬‬


‫;‪public static int x‬‬
‫{)(‪public static int getX‬‬
‫;‪return x‬‬
‫}‬
‫}‬
‫وييمكن مناداتها مباشرة باستخدام إسم الفئة بدون تعريف كائن منها‪:‬‬

‫;‪MyClass.x = 10‬‬
‫;))(‪System.out.println(MyClass.getX‬‬

‫وبهذه الطريقة ييمكن أن يكون المتغير ‪ x‬مشترك اا في القيمة بين الكائنات المختلفة‪ .‬لكن يجب الحذر والتقليل من‬
‫استخدام متغيرات مشتركة ‪ Global variables‬حيث يصعب تتبع قيمتها ويصعب معرفة القيمة الحالية لها عند‬
‫مراجعة الكود‪ .‬واﻷفضل من ذلك هو استخدام إجراءات ثابتة يتم إرسال المتغيرات لها في شكل يمدخلت كما في‬
‫المثال التالي والذي هو إجراء لتحويل اﻷحرف اﻷولى من الكلمات في جملة باللغة اللتينية إلى حرف كبير‬
‫‪ .Capital letter‬وقد يقمنا بتسميتها هذه الفئة ‪:Cap‬‬
‫{ ‪public class Cap‬‬

‫{ )‪public static String Capitalize(String input‬‬

‫;)(‪input = input.toLowerCase‬‬
‫;)(‪char[] chars = input.toCharArray‬‬

‫{ )‪for (int i=0; i < chars.length; i++‬‬


‫{ )' ' == ]‪if (i==0 || chars[i ­1‬‬

‫;)]‪chars[i] = Character.toUpperCase(chars[i‬‬

‫}‬
‫}‬
‫;)‪String result = new String(chars‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫;)‪return(result‬‬
‫}‬
‫نلحظ أننا يقمنا بكتابة إجراء من النوع الساكن ‪ static‬اسميناه ‪ Capitalize‬يقوم باستقبال متغير مقطعي اسمه‬
‫‪ input‬حيث يقوم بإرجاع متغير مقطي بعد تحويل بداية أحرفه إلى أحرف لتينية كبيرة‪.‬‬
‫في البداية يتم تحويل كافة الجملة إلى حروف لتنية صغيرة‪ ،‬ثم يتم نسخها إلى مصفوفة من نوع الرموز ‪char‬‬
‫ثم يتم تحويل اﻷحرف التي تلى المسافة إلى حروف كبيرة ويتم كذلك تحويل الحرف اﻷول في الجملة إلى حرف‬
‫كبير‪ .‬وفي النهاية تم نسخ تلك المصفوفة إلى متغير مقطعي جديد اسمه ‪ result‬ليتم إرجاعه في نداء اﻹجراء‪.‬‬
‫ويمكن مناداته مباشرة عن طريق إسم الفئة ‪ Cap‬بالطريقة التالية‪:‬‬

‫;"‪String name = "motaz abdel azeem eltahir‬‬


‫;))‪System.out.println(Cap.Capitalize(name‬‬
‫فتكون النتيجة كالتالي بعد التنفيذ‪:‬‬
‫‪Motaz Abdel Azeem Eltahir‬‬

‫ييمكن اﻹستفادة من اﻹجراءات الساكنة لكتابة مكتبة إجراءات مساععدة عامة ييمكن استخدامها في عدد من‬
‫البرامج‪ .‬مثل إجراء لكتابة اﻷخطاء التي تحدث في ملف نصي والمعروف بالـ ‪ .log fle‬أو تحويل التاريخ إلى‬
‫شكل معين ييستخدم في نوعية معينة من البرامج‪ ،‬او غيرها من اﻹجراءات التي يتستخدم بكثرة لتوفير وقت‬
‫للمبرمج‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫قاعدة البيانات ‪SQLite‬‬
‫قاعدة البيانات ‪ SQLite‬هي عبارة عن قاعدة بيانات في شكل مكتبة معتمدة على ذاتها ‪ self-contained‬للتعامل‬
‫مع قاعدة ‪ .SQLite‬وييمكن استخدام طريقة ‪ SQL‬للتعامل معها‪ .‬ويمكن استخدامها في أنظمة التشغيل المختلفة‬
‫باﻹضافة إلى الموبايل‪ ،‬مثلا في نظام أندرويد أو ‪BlackBerry‬‬

‫يمكن الحصول على المكتبة الخاصة بها وبرنامج ﻹنشاء قواعد بيانات ‪ SQLite‬والتعامل مع بياناتها من هذا‬
‫الرابط‪:‬‬

‫‪http://sqlite.org/download.html‬‬

‫ﻹستخدامها في نظام وندوز نبحث عن ملف يبدأ باﻹسم ‪ ،sqlite-shell‬أما في نظام لينكس يمكننا تثبيت تلك‬
‫المكتبة وأدواتها بواسطة مثبت الحزم‪ .‬فقط نبحث عن الحزمة ‪sqlite3‬‬

‫بعد ذلك نقوم باﻹنتقال إلى شاشة الطرفية ‪ terminal‬لتشغيل البرنامج وهو من نوع برامج سطر اﻷوامر‪ ،‬ثم‬
‫نختار دليل معين ﻹنشاء قاعدة البيانات ثم نكتب هذا اﻷمر‪:‬‬

‫‪sqlite3 library.db‬‬
‫‪SQLite version 3.7.9 2011­11­01 00:52:41‬‬
‫‪Enter ".help" for instructions‬‬
‫";" ‪Enter SQL statements terminated with a‬‬
‫>‪sqlite‬‬
‫بهذه الطريقة نكون قد أنشأنا قاعدة بيانات في ملف إسمه ‪library.db‬‬

‫والن مازلنا نستخدم هذه اﻷداة للتعامل مع قاعدة البيانات‪ .‬ثم يقمنا بإضافة جدول جديد اسمه ‪ books‬بهذه‬
‫الطريقة‪:‬‬

‫;))‪sqlite> create table books(BookId int, BookName varchar(100‬‬


‫ثم أضفنا كتابين في هذا الجدول‪:‬‬

‫;)"‪sqlite> insert into books values (1, "Introduction to Java 7‬‬


‫;)"‪sqlite> insert into books values (2, "One day trip with Java‬‬
‫ثم عرضنا محتويات الجدول‪:‬‬

‫;‪sqlite> select * from books‬‬


‫‪1|Introduction to Java 7‬‬
‫‪2|One day trip with Java‬‬
‫>‪sqlite‬‬
‫الن لدينا قاعدة بينات اسمها ‪ library.db‬وبها جدول اسمه ‪ .books‬يمكن الن التعامل معها في برنامج جافا كما‬
‫في المثال التالي‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫برنامج لقراءة قاعدة بيانات ‪SQLite‬‬
‫قبل بداية كتابة اي برنامج لقاعدة بيانات ‪ SQLite‬بواسطة جافا يجب أن نبحث عن مكتبة جافا الخاصة بها‪ .‬وهي‬
‫مكتبة إضافية غير موجودة في آلة جافا اﻹفتراضية‪ .‬وييمكن البحث عنها بدللة اﻹسم‪:‬‬

‫‪sqlite­jdbc‬‬

‫ويمكن الحصول على هذه الصفحة‪:‬‬

‫‪https://bitbucket.org/xerial/sqlite-jdbc/downloads‬‬

‫وهذا مثال ﻷحد إصدارات هذه المكتبة يمكن تحميلها‪:‬‬

‫‪sqlite­jdbc­3.8.11.2.jar‬‬

‫ييفضل اختيار النسخة اﻷحدث‪.‬‬

‫وهذه المكتبة هي يكل مانحتاجه للتعامل مع قاعدة البيانات ‪ SQLite‬في برامج جافا‪ ،‬فهي لتحتاج لمخدم لتثبيته‬
‫حتى تعمل قاعدة البيانات كما يقلنا سابقاا‪.‬‬

‫قمنا بفتح مشروع جديد أسميناه ‪ sqlitebrowser‬لعرض قاعدة البيانات ‪ Library‬التي يقمنا بإنشائها سابقاا‪.‬‬

‫في شاشة المشروع يوجد فرع أسمه ‪ Libraries‬نقف عليه ثم نختار بالزر اليمين للماوس ‪ Add JAR/Folder‬ثم‬
‫نختار الملف ‪ sqlite-jdbc-3.7.2.jar‬الذي يقمنا بتحميله من اﻹنترنت سابقاا‪.‬‬

‫أضفنا ‪ JFrame Form‬وأسميناه ‪ MainForm‬واستدعيناه من الملف الرئيسي ‪ Sqlitebrowser.java‬بالطريقة‬


‫التالية‪:‬‬

‫{ )‪public static void main(String[] args‬‬


‫;)(‪MainForm form = new MainForm‬‬
‫;)‪form.setVisible(true‬‬
‫}‬
‫في الفورم أضفنا زر و مربع نص ‪ TextArea‬بالشكل التالي‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ثم أضفنا فئة كائن جديد ‪ New class‬أسميناه ‪ SqliteClient‬وهو الكائن الذي سوف يحتوي على إجراءات قراءة‬
‫قاعدة بيانات ‪ SQLite‬والكتابة فيها‪.‬‬

‫قمنا بتعريف الكائن ‪ dbConnection‬من نوع ‪ Connection‬داخل كود فئة الكائن ‪ SqliteClient‬لتعريف مسار‬
‫قاعدة البيانات واﻹتصال بها للستخدام لحقاا في باقي إجراءات الكائن ‪.SqliteClient‬‬

‫ثم قمنا بكتابة الكود ﻹستقبال إسم قاعدة البيانات ثم اﻹتصال بها في اﻹجراء الرئيسي ‪ constructor‬لهذا الكائن‪:‬‬

‫{ ‪public class SqliteClient‬‬


‫;‪Connection dbConnection = null‬‬

‫‪// Constructor‬‬
‫{ )‪public SqliteClient (String aDatabaseName‬‬
‫;)(‪super‬‬
‫{ ‪try‬‬
‫;)"‪Class.forName("org.sqlite.JDBC‬‬
‫(‪dbConnection = DriverManager.getConnection‬‬
‫;)‪"jdbc:sqlite:" + aDatabaseName‬‬
‫}‬
‫{)‪catch (Exception e‬‬
‫;))(‪System.out.println("Error while connecting: " + e.toString‬‬
‫}‬

‫}‬

‫نلحظ أننا يقمنا بحماية الكود بواسطة ‪ try .. catch‬وذلك ﻷنه من المتوقع أن تحدث مشكلة أثناء التشغيل‪ ،‬مثلا‬

‫أن تكون قاعدة البيانات اليمدخلة غير موجودة‪ ،‬أو أن مكتبة ‪ SQLite‬غير موجودة‪.‬‬

‫اﻹجراء اﻷول)‪ (Class.forName‬يقوم بتحميل مكتبة ‪ SQLite‬لنتمكن من نداء اﻹجراءات الخاصة بهذه القاعدة‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫من تلك المكتبة التي يقمنا بتحميلها من اﻹنترنت‪ ،‬فإذا لم تكن موجودة سوف يحدث خطأ‪.‬‬

‫في السطر التالي قمنا بتهيئة الكائن ‪ dbConnection‬وإعطائه إسم الملف التي تم إرساله عند تهيئة الكائن‬
‫‪SqliteClient‬‬

‫بعد ذلك يقمنا بإضافة اﻹجراء ‪ showTable‬إلى فئة الكائن ‪ SqliteClient‬لعرض محتويات الجدول المرسل لهذا‬
‫اﻹجراء في مربع النص‪:‬‬

‫{ )‪public boolean showTable(String aTable, JTextArea textArea‬‬

‫;‪ResultSet myRecords = null‬‬


‫;‪Statement myQuery = null‬‬

‫{ ‪try‬‬
‫;)(‪myQuery = dbConnection.createStatement‬‬
‫;)‪myRecords = myQuery.executeQuery("SELECT * from " + aTable‬‬
‫‪// Read records‬‬
‫))(‪while (myRecords.next‬‬
‫{‬
‫" ­ " ‪textArea.append(myRecords.getString(1) +‬‬
‫;)"‪+ myRecords.getString(2) + "\n‬‬
‫}‬
‫{)‪catch (Exception e‬‬
‫;)"‪textArea.append("Error while reading table: " + e.toString() + "\n‬‬
‫;)‪return (false‬‬
‫}‬
‫}‬

‫قمنا في هذا اﻹجراء بتعريف كائن من نوع ‪ Statement‬أسميناه ‪ myQuery‬يسمح لنا بكتابة ‪ query‬بلغة ‪SQL‬‬
‫على‬

‫قاعدة البيانات‪.‬‬

‫وعند إضافة المكتبة المحتوية على الكائن ‪ Statement‬لبد من أن ننتبه ﻹختيار المكتبة ‪java.sql.Statement‬‬
‫ول نختار الخيار اﻷول الذي يظهر عند اﻹضافة التلقائية ‪ java.beans.Statement‬التي تتسبب في أخطاء أثناء‬
‫الترجمة‪.‬‬

‫الخيار الصحيح للمكتبة يظهر في الشكل التالي‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ثم قمنا بتهيئته على النحو التالي‪:‬‬

‫;)(‪myQuery = dbConnection.createStatement‬‬
‫ثم قمنا بنداء اﻹجراء ‪ executeQuery‬في الكائن ‪ myQuery‬وأعطيناه مقطع ‪ SQL‬والذي به أمر عرض‬
‫محتويات الجدول‪ .‬هذا اﻹجراء ييرجع كائن جديد من هو عبارة عن حزمة البيانات ‪ .ResultSet‬استقبلناه في‬
‫الكائن ‪ myRecords‬والذي هو من نوع فئة الكائن ‪ ResultSet‬والذي يقمنا بتعريفه في بداية اﻹجراء دون تهيئته‪.‬‬

‫بعد هذه اﻹجراءات يقمنا بالمرور على كل السجلت في هذا الجدول وعرضنا بعض الحقول في مربع النص الذي‬
‫تم إرساله يكمدخل للجراء ‪:showTable‬‬

‫‪// Read records‬‬


‫))(‪while (myRecords.next‬‬
‫{‬
‫" ­ " ‪textArea.append(myRecords.getString(1) +‬‬
‫;)"‪+ myRecords.getString(2) + "\n‬‬
‫}‬
‫واﻹجراء ‪ next‬يقوم بتحريك مؤشر القراءة لبداية الجدول أو حزمة البيانات ثم اﻹنتقال في كل مرة إلى السجل‬
‫الذي يليه ويرجع القيمة ‪ .true‬وعندما تنتهي السجلت أو ليكون يهناك سجلت من البداية ترجع القيمة ‪false‬‬
‫وعندها تتوقف الحلقة‪.‬‬

‫داخل الحلقة قرأنا الحقل اﻷول والثاني من الجدول اليمرسل بواسطة الدالة ‪ getString‬وأعطيناها رقم الحقل‬
‫‪ Field/Column‬وهي يترجع البيانات في شكل مقطع‪ ،‬وييمكن استخدامها حتى مع اﻷنواع اﻷخرى مثل اﻷعداد‬
‫الصحيحة مثلا أو التاريخ‪ ،‬فكلها ييمكن تمثيلها في شكل مقاطع‪.‬‬

‫في اﻹجراء التابع للزر ‪ Open‬في الفورم الرئيسي ‪ MainForm‬قمنا بكتابة هذا الكود لعرض سجلت الجدول‬
‫‪ books‬الموجود في قاعدة البيانات ‪library.db‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

SqliteClient sql = new SqliteClient("/home/motaz/library.db");

jTextArea1.setText("");
sql.showTable("books", jTextArea1);
}

‫ ثم تهيئتها بإرسال إسم‬SqliteClient ‫ من نوع الفئة التي قمنا بإنشائها‬sql ‫في السطر اﻷول قمنا بتعريف الكائن‬
.‫ وهذا المثال لبرنامج في بيئة لينكس‬.‫ملف قاعدة البيانات‬

‫ في‬showTable ‫ ثم في السطر الثالث إستدعينا اﻹجراء‬.‫ثم في السطر الثاني قمنا بحذف محتويات مربع النص‬
:‫ وكانت النتيجة كالتالي‬books ‫هذا الكائن لعرض محتويات الجدول‬

‫ أولا نقوم بإضافة إجراء جديد نسميه مثلا‬tables ‫ﻹضافة كتاب جديد في قاعدة البيانات في الجدول‬

‫ وهذا هو الكود الذي كتبناه ﻹضافة كتاب‬.showTable ‫ بعد اﻹجراء‬SqliteClient ‫ في فئة الكائن‬insertBook
:‫جديد‬

public boolean insertBook(int bookID, String bookName) {

try {
PreparedStatement insertRecord = dbConnection.prepareStatement(
"insert into books (BookID, BookName) values (?, ?)");

insertRecord.setInt(1, bookID);

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫;)‪insertRecord.setString(2, bookName‬‬
‫;)(‪insertRecord.execute‬‬
‫;)‪return(true‬‬
‫}‬

‫{)‪catch (Exception e‬‬


‫;))(‪System.out.println("Error while reading table: " + e.toString‬‬
‫;)‪return (false‬‬
‫}‬

‫في العبارة اﻷولى لهذا اﻹجراء قمنا بتعريف الكائن ‪ insertRecord‬من نوع الفئة ‪ PreparedStatement‬وهي‬
‫يتستخدم لتنفيذ إجراء على البيانات ‪ DML‬مثل إضافة سجل‪ ،‬حذف سجل أو تعديل‪ .‬ونلحظ أننا وضعنا علمة‬
‫إستفهام في مكان القيم التي ينريد إضافتها في الجزء ‪ .values‬وهذه يتسمى مدخلت ‪ .parameters‬سوف يتم‬
‫تعبئتها لحقاا‪.‬‬

‫في العبارة الثانية وضعنا رقم الكتاب في اليمدخل اﻷول بواسطة ‪ ،setInt‬ثم في العبارة الثالثة وضعنا إسم الكتاب‬
‫في اليمدخل الثاني بواسطة ‪ ،setString‬ثم قمنا بتنفيذ هذا اﻹجراء بواسطة ‪ execute‬والتي تقوم بإرسال طلب‬
‫اﻹضافة هذا إلى مكتبة ‪ SQLite‬والتي بدورها تقوم بتنفيذه في ملف قاعدة البيانات ‪library.db‬‬

‫بعد ذلك نضيف فورم ثاني من نوع ‪ JFrame Form‬ونسميه ‪ AddForm‬نضع فيه المكونات ‪ jLabel‬و ‪jTextField‬‬
‫بالشكل التالي‪:‬‬

‫‪ defaultCloseOperation‬إلى‪ Dispose‬بدلا من ‪ Exit_On_Close‬حتى‬


‫ولننسى تحويل خاصية إغلق الفورم‬
‫يتم إغلق البرنامج عند إغلق هذا الفورم الغير رئيسي‪.‬‬

‫نكتب فيه الكود التالي‪:‬‬ ‫وفي حدث الزر ‪Insert‬‬


‫{ )‪private void jButton1ActionPerformed(java.awt.event.ActionEvent evt‬‬

‫;)"‪SqliteClient query = new SqliteClient("/home/motaz/library.db‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫;‪int bookID‬‬
‫;))(‪bookID = Integer.parseInt(jTextField1.getText().trim‬‬
‫;))(‪query.insertBook(bookID, jTextField2.getText‬‬
‫;)‪setVisible(false‬‬
‫}‬
‫في السطر اﻷول قمنا بتعريف الكائن ‪ query‬من نوع الفئة ‪ SqliteClient‬والتي تحتوي إجراء اﻹضافة الذي‬
‫أضفناه‬

‫مؤخرا‪.‬‬

‫المتغير ‪ bookID‬من نوع العدد الصحيح‪.‬‬ ‫في السطر الثاني قمنا بتعريف‬

‫‪ getText‬في شكل مقطع ‪ .String‬ونحن نريده أن‬ ‫الحقل‪ jTextField1‬ييرجع محتوياته بواسطة اﻹجراء‬
‫يستقبل رقم‬

‫الكتاب وهو من النوع الصحيح والمقطع يمكن أن يحتوي على عدد صحيح‪ .‬فقمنا بتحويل المقطع إلى عدد‬
‫صحيح‬

‫بعد حذف أي مسافة غير مرغوب فيها ‪-‬إن وجدت‪ -‬بواسطة الدالة‪ trim‬الموجودة في الكائن ‪ ،String‬وذلك ﻷن‬
‫أخرى أو مسافة فإن التحويل إلى رقم بواسطة اﻹجراء‪ parseInt‬سوف‬
‫العدد إذا كان يحتوي على حروف أو رموز‬
‫ينتج عنها خطأ‪ .‬والدالة ‪ trim‬تقوم بإرجاع مقطع محذوفة فيه المسافة من بداية ونهاية النص‪ ،‬لكنها لتؤثر على‬
‫الكائن الذي تم تنفيذها فيه‪ .‬مثلا الكائن ‪ jTextField1‬ليتم حذف المسافة منه‪ .‬لتوضيح ذلك انظر المثال التالي‪:‬‬

‫;)(‪myText = aText.trim‬‬

‫الكائن ‪ aText‬ليتثأر بالدالة ‪ trim‬أما الكائن ‪ myText‬فتيم تخزين مقطع فيه من المقطع ‪ aText‬بدون مسافة‪.‬‬

‫‪ insertBook‬في الكائن ‪ query‬وأعطيناه رقم الكتاب في المدخل اﻷول‬ ‫في السطر الرابع قمنا بإستدعاء اﻹجراء‬
‫ثم‬

‫‪ setVisible‬وأعطيناها القيمة‬ ‫اسم الكتاب في المدخل الثاني‪ .‬ثم قمنا بإغلق الفورم في السطر اﻷخير بواسطة‬
‫‪.false‬‬

‫وهذا هو شكل البرنامج بعد تنفيذه‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫‪ shift + F11‬نلحظ وجود دليل فرعي إسمه ‪ lib‬داخل الدليل‬ ‫عند عمل ‪ build‬لهذا البرنامج بواسطة‬
‫على المكتبة التي استخدمناها والتي هي ليست جزء من آلة جافا اﻹفتراضية‪ .‬وعند نقل البرنامج‬ ‫‪dist‬وهو يحتوي‬
‫إلى أجهزة أخرى لبد‬
‫مع البرنامج‪ ،‬وإل تعذر تشغيل إجراءات قاعدة البيانات‪.‬‬ ‫من نقل الدليل ‪lib‬‬

‫في هذا المثال نحتاج لنقل ثلث ملفات‪:‬‬

‫وهو الملف التنفيذي للبرنامج في صيغة ‪Byte code‬‬ ‫• ‪sqlitebrowser.jar‬‬

‫وهو ملف المكتبة داخل الدليل ‪. lib‬‬ ‫• ‪sqlite­jdbc­3.7.2.jar‬‬

‫ولبد أن نضعه في هذا الدليل داخل الدليل الذي نضع فيه البرنامج‬

‫• ‪ library.db‬وهو ملف قاعدة البيانات‪ .‬وكان من اﻷفضل جعل مسار قاعدة البيانات خارج كود البرنامج‪ ،‬مثلا‬

‫نضيف ‪ jTexField‬آخر ليكون البرنامج بالشكل التالي‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ونغير تهيئة كائن قاعدة البيانات بالشكل التالي‪:‬‬

‫;))(‪SqliteClient sql = new SqliteClient(jTextField1.getText‬‬

‫‪ portable‬و ليعتمد على ثوابت في نظام معين‪ .‬وهي‬ ‫بهذه الطريقة يكون البرنامج أكثر حرية في النقل‬
‫طريقة جيدة‬

‫في تطوير البرامج تزيد من إمكانية إستخدامه‪ ،‬خصوصا عند إختيار لغة برمجة متعددة المنصات مثل جافا‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


inheritance ‫الوراثة‬
‫ وهي‬abstraction ‫ ويتستخدم الوراثة لعدة أهداف منها التجريد‬،‫الوراثة هي من أساسيات البرمجة الكائنية‬
‫ ومن تطبيقات التجريد هو إضافة إمكانات جديدة‬،‫تقسيم الفئات إلى فئة عامة مجردة وفئة متخصصة تفصيلية‬
.‫دون تغيير الفئة اﻷساسية‬
‫ و‬،‫ و حذف ملف‬،‫ و إنشاء ملف جديد‬،‫في هذا المثال قمنا بعمل فئة ﻹدارة الملفات )التأكد من وجود ملف‬
.(‫استعراض ملفات في دليل معين‬
‫ جديدة‬Class ‫ ثم قمنا بإضافة فئة‬FilesManagement ‫لعمل ذلك يقمنا أولا بإنشاء برنامج جديد اسميناه‬
source ‫ الموجودة في‬flesmanagement ‫ وذلك عن طريق الوقوف على حزمة‬FileManager ‫اسميناها‬
New/Java Class ‫ ثم الضغط بالزر اليمين في الماوس ثم اختيار‬packages
:‫ثم كتبنا هذا الكود داخل هذه الفئة الجديدة‬
package filesmanagement;

import java.io.File;

public class FileManager {

public boolean checkExistence(String filename){

File file = new File(filename);


return file.exists();
}

public boolean createFile(String filename){

try {
File file = new File(filename);
file.createNewFile();
return true;
}
catch (Exception ex){
System.out.println("Unable to create file: " + ex.toString());
return false;
}

public boolean deleteFile(String filename){


try {
File file = new File(filename);
file.delete();
return true;
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫{)‪catch (Exception ex‬‬
‫;))(‪System.out.println("Error while deleting file: " + ex.toString‬‬
‫;‪return false‬‬
‫}‬
‫}‬

‫{)‪public String[] listFiles(String directory‬‬

‫;)‪File dir = new File(directory‬‬

‫;)(‪File files[] = dir.listFiles‬‬

‫;]‪String fileNames[] = new String[files.length‬‬

‫‪// Fill file names array‬‬


‫{)‪for (int i=0; i<files.length; i++‬‬
‫;)(‪fileNames[i] = files[i].getName‬‬
‫}‬

‫;‪return fileNames‬‬
‫}‬
‫}‬

‫ثم قمنا بتعريف وتهيئة ثم استخدام كائن من هذه الفئة في البرنامج الرئيسي كالتالي‪:‬‬

‫{ )‪public static void main(String[] args‬‬

‫;)(‪FileManager manager = new FileManager‬‬

‫{ ))"‪if (! manager.checkExistence("/home/motaz/testing/first.txt‬‬
‫;)"‪manager.createFile("/home/motaz/testing/first.txt‬‬
‫}‬
‫;)"‪String files[] = manager.listFiles("/home/motaz/testing‬‬

‫‪// List files‬‬


‫{)‪for (String filename: files‬‬
‫;)‪System.out.println(filename‬‬
‫}‬
‫}‬

‫نلحظ أن هذه الفئة عامة في التعامل مع الملفات‪ ،‬حيث أن أي نوع ملف يمكن أن نتأكد من وجوده أو من عدم‬
‫وجوده‪ ،‬كذلك إنشاءه وحذفه واستعراض أسماء ملفات في دليل معين ايضاا هي ميزة مشتركة بين أنواع الملفات‬
‫المختلفة‪ ،‬حيث تشترك فيها كل أنواع الملفات سوااء كانت نصية‪ ،‬أو ملفات صوتية أو صور أو فيديو أو حتى‬
‫ملفات تنفيذية‪ .‬هذا ما ينسمية بالتجريد بأن تكون هذه الفئة عامة الستخدام وغير مخصصة لنوع معين من‬
‫الملفات‪ ،‬فإذا قمنا بإدخال إجراء مثلا لقراءة ملف نصي داخل نفس الفئة فنكون قد كسرنا التجرد الذي يتمثله هذه‬
‫الفئة‪ ،‬حيث ل يمكن استعراض ملف صورة مثلا بهذه اﻹجراء الجديد‪ ،‬فاصبح يهناك إستثناءات في اجراءات هذه‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


.‫ وهذا لم يكن الهدف وراء إنشاء هذه الفئة من اﻷساس‬،‫الدالة تعتمد على نوع الملف‬
‫للمحافظة على تجريد الفئة السابقة دون تغيير قوانينها مع تحقيق هدف إضافة هذا اﻹجراء الجديد نقوم بإنشاء‬
‫ لكن حتى ل تضيع اﻹجراءات الموجودة‬،‫ ﻹضافة هذا اﻹجراء الجديد‬TextFileManager ‫فئة جديدة ينسميها‬
.‫ نقوم بوراثة الفئة اﻷخيرة بما تحتويه من إجراءات في الفئة الجديدة‬FileManager ‫أصلا في الفئة‬
: ‫ ثم أضفنا عبارة‬TextFileManager ‫ ثم أسميناها‬New/Java Class ‫قمنا بإضافة هذه الفئة عن طريق‬
extends FileManager
:‫ليصبح كود الفئة كالتالي‬
public class TextFileManager extends FileManager {

readTextFile ‫ثم بعد ذلك نشرع في إضافة اﻹجراء الجديد‬

public void readTextFile(String fileName){

try {

FileReader reader = new FileReader(fileName);


char buf[] = new char[1024];
int numread;
while ((numread=reader.read(buf)) != ­1){
String text = new String(buf, 0, numread);
System.out.print(text);
}
reader.close();

} catch (Exception ex){


System.out.println("Error while reading file: " + ex.toString());
}

:‫ايضاا يمكننا إضافة إجراء آخر للكتابة في ملف نصي‬

public void writeIntoTextFile(String fileName, String lines){

try {

// Check file existence


if (!checkExistence(fileName)) {
createFile(fileName);
}

FileWriter writer = new FileWriter(fileName);

Code.sd ‫كود لبرمجيات الكبيوتر‬


writer.write(lines);
writer.close();

} catch (Exception ex){


System.out.println("Error while writing into file: " + ex.toString());
}
}

FileManager ‫ الموروثة من الفئة اﻷم‬createFile ‫ و‬checkExistence :‫نلحظ أننا استخدمنا اﻹجرائين‬


TextFileManager ‫وكأنها موجودة معنا في نفس الفئة الحالية‬

‫ ونلحظ أنه يمكننا نداء إجراءات الفئة اﻷساسية‬،‫في اﻹجراء الرئيسي قمنا بإنشاء كائن من الفئة الجديدة‬
:‫ باﻹضافة ﻹجراءات الفئة الجديدة‬FileManager

public static void main(String[] args) {

TextFileManager manager = new TextFileManager();

if (! manager.checkExistence("/home/motaz/testing/first.txt")) {
manager.createFile("/home/motaz/testing/first.txt");
}
String files[] = manager.listFiles("/home/motaz/testing");

// List files
for (String filename: files){
System.out.println(filename);
}

manager.writeIntoTextFile("/home/motaz/testing/second.txt",
"This is a test file\n written using inheritance\n");
manager.readTextFile("/home/motaz/testing/second.txt");
}

‫ لكن عملنا إضافات خاصة في فئتنا الجديدة‬FileManager ‫بهذه الطريقة لم ينعدل على الفئة‬
‫ يمكن كذلك عمل فئات متخصصة في أي نوعية أخرى من‬.‫ المتخصصة في الملفات النصية‬TextFileManager
.FileManager ‫الملفات بعد الوراثة من الفئة الرئيسة‬
‫ حيث يكون‬،‫نكون كذلك قد حققنا إعادة استخدام الكود بدلا من تكراره كل مرة مع الفئات المتخصصة الجديدة‬
.‫ و كل هذا ييعتبر من الطرق المثلى لكتابة البرامج‬.‫هناك دائماا إجراءات مشتركة‬

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫تكرار حدث بواسطة مؤقت‬
‫في هذا المثال ينريد كتابة التاريخ والساعة في الشاشة كل فترة معينة‪ ،‬مثلا كل ثانية‪ .‬ولعمل ذلك قمنا بفتح‬
‫مشروع جديد سميناه ‪ timer‬ثم أضفنا ‪ MainForm‬من نوع ‪ ،JFrame Form‬ثم أضفنا فئة جديدة ‪new class‬‬
‫أسميناها ‪ MyTimer‬فكان تعريفها بالشكل التالي‪:‬‬

‫{ ‪public class MyTimer‬‬

‫لكن قمنا بتغير هذا التعريف لنستخدم الوراثة التي ذكرناها سابقاا‪ ،‬وذلك بدلا من كتابة فئة كائن جديد من الصفر‬
‫نستخدم فئة لديها خصائص مشابهة ثم نزيد فيها‪ .‬وفئة هذا الكائن اسمها ‪ .TimerTask‬نقوم بوراثته بهذه‬
‫الطريقة‪:‬‬

‫{‪public class MyTimer extends TimerTask‬‬

‫ثم نقوم بتعريف كائن ‪ myLabel‬بداخله حتى نقوم بعرض التاريخ والوقت فيه‪ ،‬ثم قمنا بكتابة إجراء التهيئة‪:‬‬

‫;‪JLabel myLabel‬‬

‫{)‪public MyTimer(JLabel alabel‬‬


‫;)(‪super‬‬
‫;‪myLabel = alabel‬‬
‫}‬

‫وفي هذا اﻹجراء نستقبل الكائن ‪ alabel‬ثم نقوم بحفظ نسخة منه في الكائن ‪.myLabel‬‬

‫بعد ذلك نقوم بكتابة اﻹجراء الذي سوف يتم إستدعائه كل فترة وأسمه ‪ run‬بهذه الطريقة‪:‬‬

‫‪@Override‬‬
‫{ )(‪public void run‬‬
‫;)(‪Date today = new Date‬‬
‫;))(‪myLabel.setText(today.toString‬‬

‫}‬
‫ويمكن إضافة تعريف هذا اﻹجراء تلقائياا بواسطة ‪ implement all abstract methods‬والتي تظهر في سطر‬
‫تعريف الكائن ‪ MyTimer‬بالطريقة التالية‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


:‫وهذا هو كود الكائن كاملا‬

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package timer;

import java.util.Date;
import java.util.TimerTask;
import javax.swing.JLabel;

/*
*
* @author motaz
*/
public class MyTimer extends TimerTask{
JLabel myLabel;
public MyTimer(JLabel alabel){
super();
myLabel = alabel;
}

@Override
public void run() {
Date today = new Date();
myLabel.setText(today.toString());

:‫ ونزيد حجم الخط فيه ليكون بالشكل التالي‬MainForm ‫ في الفورم الرئيسي‬jLabel ‫نضع‬

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫في إجراء تهيئة هذا الفورم نعدل الكود إلى التالي‪:‬‬

‫{ )(‪public MainForm‬‬
‫;)(‪initComponents‬‬
‫;‪java.util.Timer generalTimer = null‬‬

‫;)‪MyTimer timerObj = new MyTimer(jLabel1‬‬


‫;)"‪generalTimer = new java.util.Timer("time loop‬‬
‫;)‪generalTimer.schedule(timerObj, 2000, 1000‬‬
‫}‬
‫في هذا السطر‪:‬‬

‫;‪java.util.Timer generalTimer = null‬‬

‫قمنا بتعريف الكائن ‪ generalTimer‬من النوع ‪ .Timer‬وهذا الكائن لديه خاصية تكرار الحدث بفترة زمنية‬
‫محددة‪.‬‬

‫ثم قمنا بتعريف الكائن ‪ timerObj‬من الفئة ‪ MyTimer‬والتي قمنا بكتابتها ﻹظهار التاريخ والوقت‪.‬‬

‫ثم قمنا بتهيئة الكائن ‪ .generalTimer‬وفي السطر اﻷخير قمنا بتشغيل اليمؤقت ‪ shedule‬وأرسلنا له الكائن‬
‫‪ timerObj‬ليقوم بنتفيذ اﻹجراء ‪ run‬كل فترة معينة‪ .‬والرقم اﻷول ‪ 2000‬هو بداية التشغيل أول مرة‪ ،‬وهو بالملي‬
‫ثانية‪ ،‬أي يقوم باﻹنتظار ثانيتين ثم التشغيل أول مرة‪.‬‬

‫الرقم الثاني ‪ 1000‬هو التكرار بالملي ثانية أيضاا‪ .‬حيث يقوم بإظهار التاريخ والوقت كل ثانية‪.‬‬

‫نقوم بتشغيل البرنامج لنرى أن الثواني تتغير في الفورم الرئيسي‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫وسوف يتم تشغيل هذا اﻹجراء تلقائياا إلى إغلق البرنامج‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫برمجة الويب باستخدام جافا‬
‫تعتبر لغة جافا من أهم اللغات التي تدعم برمجة الويب ‪ web applications‬وخدمات الويب ‪web services‬‬
‫مثل الـ ‪ SOAP‬والـ ‪ .RESTfull‬والتقنية التي استخدمناها هنا في شرح برامج الويب هي تقنية ‪ Servlet‬و ‪.JSP‬‬
‫وفي النهاية يتم تشغيل برامج الويب وخدمات الويب المكتوبة بجافا في مخدم ويب خاص مثل ‪Apache‬‬
‫‪ Tomcat‬أو ‪.GlassFish‬‬

‫تثبيت مخدم الويب‬


‫قبل البداية في كتابة برامج ويب يجب التأكد من أنه يوجد مخدم ويب خاص بجافا وأن له إعدادات في بيئة‬
‫التطوير ‪ NetBeans‬وذلك عن طريق ‪ Tools/Servers‬فتظهر هذه الشاشة‪:‬‬

‫ويظهر فيها وجود ‪ GlassFish‬و ‪. Tomcat‬‬

‫وييفضل تثبيت ‪ Tomcat‬أثناء تثبيت ‪ NetBeans‬باختيار ‪ Customize‬كالتالي‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ثم اختيار ‪ Tomcat‬بدلا عن ‪Glassfsh‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫وفي حالة أننا لم نقم بعمل الخطوة السابقة أثناء التثبيت وعدم وجود ‪ ،Tomcat‬حينها قوم بالحصول عليه من‬
‫موقع ‪ . tomcat.apache.org‬نختار منه الملف الذي ينتهي باﻹمتداد ‪ zip.‬كما يظهر في هذه الشاشة‪:‬‬

‫بعد ذلك نقوم بفك الملف في مكان معروف‪ ،‬ثم نقوم بإضافة مخدم جديد عن طريق الزر ‪ Add Server‬ثم نختار‬
‫رقم نسخة ‪ Tomcat‬التي قمنا بتثبيتها ثم يندخل الدليل الذي توجد فيه كما في هذا المثال‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫عند الحاجة لتثبيت برامج الويب في أجهزة أخرى )مخدم مثلا( نقوم بتثبيت نسخة ‪ Apache Tomcat‬بطريقة‬
‫مختلفة حسب نظام التشغيل المستهدف‪ ،‬من الموقع‪:‬‬
‫‪http://tomcat.apache.org/‬‬
‫في بيئة وندوز نقوم باختيار الملف‪:‬‬
‫)‪32-bit/64-bit Windows Service Installer (pgp, md5, sha1‬‬

‫ثم نقوم بإدخال إسم المستخدم والذي سوف نستخدمه لحقاا لرفع البرامج وإدارة مخدم الويب‪.‬‬

‫أما في نظام لينكس فيمكن تثبيته عن طريق مدير الحزم‪ ،‬في نظام اوبونتو أو انظمة ديبيان عموماا نكتب‪:‬‬
‫‪sudo apt-get install tomcat7 tomcat7-admin‬‬
‫ويمكن استبدالها بـ ‪ tomcat8‬أو ‪ tomcat9‬حسب إصدارة لينكس المستخدمة‪.‬‬
‫كذلك يمكن تثبيت ينسخة تعمل مع جميع أنظمة لينكس بتحميلها من موقع ‪ tomcat‬واختيار الملف الذي ينتهي‬
‫باﻹمتداد ‪zip.‬‬
‫بعد ذلك نبحث عن الملف ‪ tomcat-users.xml‬في دليل اﻹعدادات حسب نظام التشغيل‪ ،‬وحسب نسخة الـ‬
‫‪ tomcat‬مثلا في بيئة لينكس يكون في هذا المسار‪:‬‬
‫‪/etc/tomcat7/tomcat­users.xml‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


:‫ وذلك إذا احتجنا إلى تغيير اسم الدخول أو كلمة المرور‬،‫في نظام وندوز يكون في هذا المسار‬
C:\Program Files\Apache Software Foundation\Tomcat 8.0

:‫نقوم بإضافة هذا السطر لمستخدم جديد أو تعديل مستخدم موجود ﻹعطائه الصلحيات الكافية‬

<user username="motaz" password="tomcat" roles="manager­gui,manager­script"/>

.‫عندها تكون البيئة جاهزة لتثبيت وتشغيل برامج أو خدمات ويب‬

‫أول برنامج ويب‬


‫لعمل برنامج الويب اﻷول في جافا نقوم بعمل مشروع جديد عن طريق‬

New project\Java Web\Web Application


‫ ثم نضغط على زر‬Tomcat ‫ وهو في هذه الحال‬،‫ ثم نختار المخدم‬frstweb ‫ثم نختار إسم للمشروع مثلا‬
.Finish

:‫ تلقائياا كصفحة رئيسة كما يلي‬HTML ‫عندها يتم إضافة كود‬

<!DOCTYPE html>
<!­­
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
­­>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF­8">
<meta name="viewport" content="width=device­width, initial­scale=1.0">
</head>
<body>
<div>TODO write content</div>
</body>
</html>
</html>

‫ إلى‬TODO write content ‫ييمكنن تعديل عبارة‬


<h1>Hello World!</h1>

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫ثم حفظ التغييرات و تشغيل البرنامج مباشرة من بيئة ‪ NetBeans‬بواسطة المفتاح ‪ F6‬ليتم عرض هذه الصفحة‬
‫بواسطة تشغيل مخدم ‪ Tomcat‬لتظهر على متصفح خاص بالشكل التالي‪:‬‬

‫نلحظ أن العنوان هو‪:‬‬


‫‪http://localhost:8084/firstweb/‬‬

‫ويظهر فيه رقم المنفذ ‪ 8084‬والمنفذ اﻹفتراضي لمخدم الـ ‪ tomcat‬هو ‪ 8080‬لكن اﻷخير ييستخدم في حالة‬
‫التثبيت النهائي للبرنامج لستخدامه من قبل مستخدمي النظام‪ ،‬أما المنفذ اﻷول فييستخدم مع ‪NetBeans‬‬
‫لتطوير برامج الويب‪ ،‬ويمكن أن يحتوي الكمبيوتر على أكثر من نسخة ‪ tomcat‬يعملن في نفس الوقت‪ ،‬لكن كل‬
‫واحد لديه منفذ مختلف‪.‬‬

‫نقوم بإغلق المتصفح لنرجع للبرنامج لنضيف فيه محتوي تفاعلي‪ ،‬حيث أن الصفحة السابقة كانت صفحة ثابتة‬
‫‪ static‬أو أنها تستخدم تقنية مختلفة وهي ‪.HTML‬‬

‫في شجرة المشروع وفي الفرع ‪ Source Packages‬نقوم بإضافة ‪ Servlet‬عن طريق الزر اليمين للماوس ثم‬
‫‪ .New‬ثم نقوم بتسميته ‪ Timer‬كما في الشكل التالي‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


ProcessRequest ‫ ليظهر كود تلقائي يحتوي على اﻹجراء‬.‫ بنفس اﻹسم مثلا‬package ‫نقوم بتسمية الحزمة‬
:‫كما في المثال التالي‬
protected void processRequest(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF­8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Timer</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet Timer at " + request.getContextPath() +
"</h1>");
out.println("</body>");
out.println("</html>");
}
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫نقوم بإضافة هذا الكود بعد السطر المكتوب فيه ‪Servlet Timer at‬‬
‫;)(‪Date today = new Date‬‬
‫;)">‪out.println("Time in server is: <b>" + today.toString() + "</b‬‬
‫ثم نقوم بتشغيله مرة أخرى لكن نضيف في عنوان التصفح إسم ال ‪ Servlet‬وهو ‪ Timer‬كالتالي‪:‬‬

‫لستقبال يمدخلت عن طريق العنوان نضيف السطر التالي في البرنامج‪:‬‬

‫)"‪out.println("<br>Your name is: <font color=green>" + request.getParameter("name‬‬


‫;)">‪+ "</font‬‬

‫وذلك بإعتبار أنه سوف يتم إدخال إسم المستخدم في العنوان كالتالي‪:‬‬
‫‪http://localhost:8084/firstweb/time?name=Mohammed‬‬
‫فتكون النتيجة كالتالي في المتصفح‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫تثبيت برامج الويب‬
‫بعد اﻹنتهاء من تطوير برامج الويب نقوم بإنتاج نسخة تنفيذية بواسطة ‪ Clean and Build‬لنتحصل على الملف‬
‫‪ frstweb.war‬وهو ملف تنفيذي ييمكن وضعه في مخدم ‪ Tomcat‬الذي ينريد تثبيت البرنامج فيه‪ .‬ونضعه في‬
‫الدليل ‪ webapps‬ضمن دليل برنامج ‪ .Tomcat‬مثلا في نظام لينكس يكون إسم الدليل هو‪:‬‬
‫‪/var/lib/tomcat7/webapps/‬‬
‫وفي نظام ويندوز نجده في الدليل ‪:‬‬
‫‪Program Files\Apache Software foundation\Tomcat 7\webapps‬‬

‫هذه المرة نستخدم ينسخة ‪ tomcat‬المعدة للتثبيت النهائي للنظام والتي تكلمنا عنها سابقاا والتي تستخدم المنفذ‬
‫‪8080‬‬
‫لنحتاج لنسخ الملف يدوياا إلى الدليل ‪ webapps‬بل نستخدم مدير برامج الويب في مخدم ‪ Tomcat‬عن طريق‬
‫المتصفح‪ ،‬حيث نكتب العنوان التالي‪:‬‬
‫‪http://localhost:8080‬‬
‫ثم نضغط رابط ‪ Manager Webapp‬ونقوم بإدخال إسم الدخول الذي اضفناه سابقاا لتظهر لنا الشاشة التالية في‬
‫المتصفح‪:‬‬

‫في الجزء ‪Deploy/War fle to deploy‬‬


‫نقوم برفع الملف ثم نضغط على زر ‪ Deploy‬ليتم نسخ الملف في دليل ‪ webapps‬ليصبح متوفراا للستخدام‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫تقنية ‪JSP‬‬
‫كلمة ‪ JSP‬هي اختصار لـ ‪ Java Server Page‬وهي مشابهة لطريقة برمجة الويب في لغة ‪ PHP‬أو ‪ ASP‬حيث يتم‬
‫إضافة صفحة تنتهي باﻹمتداد ‪ jsp.‬ويمكنها أن تحتوي على ‪ HTML‬وكود جافا‪ .‬ويمكن عمل برنامج جافا ويب‬
‫يحتوي على تقنيتي ‪ JSP‬و ‪ Servlet‬في آن واحد‪.‬‬
‫نقوم بإضافة ملف جديد في نفس المشروع ‪ ،frstweb‬لكن هذه المرة في ‪ web pages‬بدلا عن ‪Source‬‬
‫‪ Package‬والتي نضيف فيها الـ ‪.Servlet‬‬
‫نضغط بالزر اليمين على ‪ Web Pages‬ثم نختار ‪ New/JSP‬ثم نقوم بتسميته ‪ frst‬كالتالي‪:‬‬

‫لنتحصل على الملف ‪ frst.jsp‬يحتوي على هذه المحتويات‪:‬‬

‫­­‪<%‬‬
‫‪Document‬‬ ‫‪: first‬‬
‫‪Created on : May 27, 2016, 12:10:27 PM‬‬
‫‪Author‬‬ ‫‪: motaz‬‬
‫>‪­­%‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


<%@page contentType="text/html" pageEncoding="UTF­8"%>
<!DOCTYPE html>
<html>
<head>
<meta http­equiv="Content­Type" content="text/html; charset=UTF­8">
<title>JSP Page</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>

:‫ ﻹسم البرنامج ليظهر كالتالي‬frst.jsp ‫ نقوم بإضافة‬،‫عند تشغليه في المتصفح‬

‫ ﻹضافة كود جافا لها نقوم بكتابة الكود بين علمتي‬،HTML ‫ أي فقط‬،‫وهي عبارة عن صفحة ثابتة‬
<% %>
:‫كالتالي‬

<%­­
Document : first
Created on : May 27, 2016, 12:10:27 PM
Author : motaz
­­%>

<%@page contentType="text/html" pageEncoding="UTF­8"%>


<!DOCTYPE html>
<html>
<head>
<meta http­equiv="Content­Type" content="text/html; charset=UTF­8">
<title>JSP Page</title>

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫>‪</head‬‬
‫>‪<body‬‬
‫>‪<h1>Hello World!</h1‬‬
‫‪<%‬‬
‫;‪int x = 10‬‬
‫;)‪out.println("X = " + x‬‬
‫>‪%‬‬
‫>‪</body‬‬
‫>‪</html‬‬

‫يتم استخدام ملفات ‪ JSP‬في حال أن كود الـ ‪ HTML‬اكثر من كود جافا‪ ،‬ويتم استخدام تقنية ‪ Servlet‬في حال أن‬
‫كود جافا أكثر من الـ ‪ .HTML‬او بمعني آخر يتم استخدام ‪ Servlet‬في حال أن كود جافا أكثر كود العرض‬
‫‪.presentation‬‬
‫تتميز ايضاا ملفات ‪ JSP‬على أنها يتم وضعها في المخدم كما هي ‪ source code‬ويمكن تعديلها بعد تثبيتها في‬
‫المخدم‪ ،‬أي يمكن الوصول إليها داخل دليل ‪ tomcat/webapps‬فنجدها مكتوبة كمصدر برنامج يمكن قراءته‬
‫وتعديله‪ ،‬بخلف الـ ‪ Servlet‬والتي نجدها في المخدم في شكل ملفات ‪ class byte code‬ل يمكن قراءتها‬
‫وتعديلها‪.‬‬
‫في الجانب العملي يتم استخدام التقنيتين في معظم برامج الويب المكتوبة بلغة جافا‪ ،‬فيتم استقبال المستخدم‬
‫بواسطة ملف ‪ JSP‬الذي يمثل واجهة المستخدم الموجود فيها الـ ‪ HTML‬و الـ ‪ Java script‬والـ ‪ CCS‬وكود الجافا ‪،‬‬
‫وعندما يقوم بمليء الفورم مثلا يتم استقبال هذه المدخلت ومعالجتها بواسطة ‪.Servlet‬‬
‫لتوضيح ذلك نقوم بإضافة هذا الكود في الملف ‪frst.jsp‬‬

‫>‪<html‬‬
‫>‪<head‬‬
‫>"‪<meta http­equiv="Content­Type" content="text/html; charset=UTF­8‬‬
‫>‪<title>JSP Page</title‬‬
‫>‪</head‬‬
‫>‪<body‬‬
‫>‪<h1>Hello World!</h1‬‬
‫‪<%‬‬
‫;‪int x = 10‬‬
‫;)‪out.println("X = " + x‬‬
‫>‪%‬‬
‫>"‪<form action="Timer‬‬
‫‪Please enter your name‬‬
‫>‪<input type="text" name="username" /‬‬

‫>‪<br/‬‬
‫>‪<input type="submit" /‬‬

‫>‪</form‬‬
‫>‪</body‬‬
‫>‪</html‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ثم نقوم بإضافة السطر التالي للـ ‪ Servlet Timer‬كالتالي‪:‬‬
‫‪out.println("<br>Hello <font color=blue>" + request.getParameter("username") +‬‬
‫;)">‪"</font‬‬

‫ثم عند عرض الـ ‪ JSP‬تظهر شاشة اﻹدخال‪ ،‬وعند كتابة اﻹسم وضغط زر ‪ Submit Query‬يتم نداء الـ ‪Servlet‬‬
‫كالتالي‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫خدمات الويب ‪Web services‬‬
‫خدمات الويب هي عبارة عن برامج مشابهة لبرامج الويب إل أن الفرق اﻷساسي هو أن برامج الويب كما في‬
‫المثال السابق تتم كتابتها ليتم الوصول إليها عن طريق المتصفح مباشرة‪ ،‬أما خدمات الويب فيتم الوصول إليها‬
‫بواسطة برامج أخرى‪ .‬وبمعنى آخر في برامج الويب يقوم المتصفح بطلب عنوان صفحة أو ‪ action‬فيتم الرد على‬
‫المتصفح بتحميل صفحة ‪ HTML‬أو صورة أو غيرها من اﻷشياء التي يستطيع التعامل معها متصفح الويب‪ .‬أما‬
‫خدمة الويب فيتم فيها كتابة إجراء يتم نداءه عن طريق برنامج آخر هو عميل لخدمة الويب ‪web service‬‬
‫‪ .client‬مثلا يقوم أحد المبرمجين بكتابة خدمة ويب لحجز تذكرة سفر لصالح شركة خطوط طيران مث ا‬
‫ل‪ ،‬وذلك‬
‫بد ا‬
‫ل من أن يكون البرنامج في شكل صفحة عن طريق اﻹنترنت‪ .‬فيقوم مبرمج آخر يعمل لصالح وكالة سفر بها‬
‫برنامج ﻹدارة الوكالة أن يقوم بتضمين نداء إجراء حجز التذكرة من ذلك البرنامج بدلا من أن يقوم الموظف بفتح‬
‫صفحة في اﻹنترنت لحجز تلك التذكرة‪ .‬وليس شرط أن يتم نداء اﻹجراء بنفس اللغة التي تمت كتابة خدمة‬
‫الويب بها‪ .‬وهذه ميزة مهمة في برامج خدمات الويب‪.‬‬
‫وهذا هو مثال لطريقة تصميم نظام به خدمة ويب وييسمى نظام متعدد الطبقات‪:‬‬

‫نجد أنه في التصميم توجد ثلث طبقات‪:‬‬


‫قاعدة البيانات والتي تحتوي على بيانات المؤسسة‬ ‫•‬
‫مخدم برامج خدمات الويب وييسمى أحياناا بالطبقة الوسيطة ‪ middle tier‬وهو يحتوي على إجراءات‬ ‫•‬
‫تحتاجها البرامج العميلة يتم تنفيذها في قاعدة البيانات أو أي مورد آخر من موارد المؤسسة‬
‫الطبقة اﻷخيرة هي طبقة برنامج العميل ‪ client application‬وبه نداء ﻹجراءات يتم تنفيذها في‬ ‫•‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫المخدم الوسيط‪.‬‬

‫طريقة معمارية تعدد الطبقات لها عدة فوائد منها‪:‬‬

‫‪ .1‬عزل قاعدة البيانات ومخدمها عن اﻷجهزة العميلة‪ ،‬وهذا ييقلل نقاط اﻹتصال على قاعدة البيانات‪ .‬فإذا‬
‫ل‪ ،‬فبد ا‬
‫ل من أن يتم عمل مائة نقطة إتصال مباشر مع قاعدة البيانات من‬ ‫كانت مؤسسة بها مائة عميل مث ا‬

‫أجهزة العملء‪ ،‬يتم تجميع تلك اﻹتصالت في مخدم وسيط واحد أو إثنين وبدورها تقوم تلك اﻷجهزة‬
‫الوسيطة بالتعامل مع قاعدة البيانات‪.‬‬

‫‪ .2‬لنحتاج لتثبيت مكتبات للوصول لقاعدة البيانات في أجهزة العملء‪ ،‬فقط يكفي تثبيت مكتبة التعامل مع‬
‫قاعدة البيانات في اﻷجهزة الوسيطة‪ .‬فإذا تم تغيير تلك المكتبة أو حتى إذا تم تغيير محرك قاعدة‬
‫البيانات نفسها يتم عمل هذا التغيير في البرامج الوسيطة فقط‪.‬‬

‫‪ .3‬زيادة تأمين وسرية قاعدة البيانات‪ .‬حيث قمنا بعزل العميل عن قاعدة البيانات‪ .‬فييمكن أن يتم حصر‬
‫سماحية الوصول إلى قاعدة البيانات عن اﻷجهزة الوسيطة فقط‪.‬‬

‫‪ .4‬وسيلة إتصال ومخاطبة برمجية بين المؤسسات المختلفة‪ :‬فل يمكن لبنك مثلا أن يقوم بالسماح لبنك آخر‬
‫أو أ مؤسسة أخرى للدخول على قاعدة بياناته لتنفيذ عمليات معينة‪ ،‬إنما يتم عمل خدمات ويب محصورة‬
‫في هذه الخدمات التي يطلبها البنك الخر وإعطاءه صلحية لندائها‪.‬‬

‫‪ .5‬وسيلة إتصال بين اﻷنظمة المختلفة في المؤسسة الواحدة‪ .‬حيث ييمكن لمؤسسة أن يكون لديها أكثر من‬
‫نظام من جهات مختلفة‪ ،‬ولتكامل تلك اﻷنظمة مع بعضها ييمكن أن يوفر كل نظام خدمات ويب تسمح‬
‫للنظمة اﻷخرى اﻹستفادة منه‪ .‬فمثلا إذا كان يهناك نظام ﻹرسال رسائل نصية فبدلا من إعطاء البرامج‬
‫اﻷخرى صلحية على قاعدة البيانات ﻹرسال تلك الرسائل ييفضل أن يكون لديه خدمات ويب ﻹرسال‬
‫وإستقبال الرسائل الموجهة إلى البرامج اﻷخرى‪.‬‬

‫‪ .6‬التقليل من التحديثات المستمرة في برامج العملء‪ .‬ففي أغلب اﻷحيان يكون التحديث واﻹضافات في‬
‫النظام تحدث في قاعدة البيانات والطبقة الوسيطة ولتتأثر البرامج الطرفية في أجهزة العملء بهذا‬
‫التغيير‪ ،‬فنقلل بذلك تكلفة صيانة ومتابعة الينسخ عند المستخدمين‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫برنامج خدمة ويب للكتابة في ملف‬
‫في هذا المثال نريد كتابة خدمة ويب من نوع تقينة الـ ‪ SOAP‬بها إجراء ﻹستقبال نص وكتابته في ملف نصي‪ ،‬ثم‬
‫كتابة إجراء آخر لقراءة محتويات الملف النصي الذي تتم الكتابة فيه‪.‬‬

‫نقوم بإنشاء برنامج جديد من نوع ‪ Java Web/Web Application‬ونسميه ‪ logfle‬ثم نختار ‪ tomcat‬كمخدم‬
‫ويب له‪:‬‬

‫بعد ذلك نقوم بإضافة حزمة جديدة ينسميها ‪Log‬‬


‫في ‪:Source Packages‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


:‫ كما في الصورة التالية‬Mylog ‫ نسميها‬Web Service ‫ نقوم بإضافة‬Log ‫وفي الحزمة الجديدة‬

.‫ فنقوم بإختيار موافقة‬،METRO ‫بعدها يتم التنبيه على أنه سوف يتم إضافة مكتبة‬
:Mylog.java ‫يتم إضافة الكود التلقائي التالي في الملف‬

*/
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Log;

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;

/**
*
* @author motaz
*/
@WebService(serviceName = "Mylog")
public class Mylog {

/**
* This is a sample web service operation
*/

Code.sd ‫كود لبرمجيات الكبيوتر‬


@WebMethod(operationName = "hello")
public String hello(@WebParam(name = "name") String txt) {
return "Hello " + txt + " !";
}
}
:‫ في بداية تعريف خدمة الويب لنضع فيها اﻷخطاء التي تحدث‬lastError ‫أولا نقوم بإضافة متغير مقعطي اسمه‬

@WebService(serviceName = "Mylog")
public class Mylog {

public String lastError = "";

‫ فنضيف إجراء‬،Mylog ‫ عند فتحها نجد‬Web Services ‫ونجد أيضاا أنه تم إضافة فرع جديد في المشروع إسمه‬
Add Operation ‫جديد فيه بواسطة‬

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫ من النوع المقطعي‬text ‫ ويستقبل متغير اسمه‬boolean ‫ وهو يرجع النوع‬.insertLog ‫نقوم بتسمية ذلك اﻹجراء‬
:‫ كما في الصورة التالية‬String

: insertLog ‫ نجد أنه تم إضافة اﻹجراء‬Mylog.java ‫وإذا رجعنا مرة إخرى للملف‬
@WebService(serviceName = "Mylog")
public class Mylog {

/**
* This is a sample web service operation
*/
@WebMethod(operationName = "hello")
public String hello(@WebParam(name = "name") String txt) {
return "Hello " + txt + " !";
}

/**
* Web service operation
*/
@WebMethod(operationName = "insertLog")
public Boolean insertLog(@WebParam(name = "text") String text) {
//TODO write your implementation code here:
return null;
}
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


:‫بعدها قمنا بإستلف إجراء الكتابة في ملف نصي من مثال سابق وعمل بعض التعديلت‬

private boolean writeToTextFile(String aFileName, String text)


{
try{
FileOutputStream fstream = new FileOutputStream(aFileName, true);

DataOutputStream textWriter = new DataOutputStream(fstream);

textWriter.writeBytes(text);
textWriter.close();
fstream.close();
return (true); // success

}
catch (Exception e)
{
lastError = e.getMessage();
return (false); // fail
}

:‫ بالطريقة التالية‬insertLog ‫ ليتم إستدعاءه من اﻹجراء‬Mylog.java ‫وأضفناه في نهاية الملف‬

@WebMethod(operationName = "insertLog")
public Boolean insertLog(@WebParam(name = "text") String text) {

boolean result = writeToTextFile("/tmp/mylog.txt", text);

return result;
}
‫ كما في المثال السابق لكن بدون أن‬Add Operation ‫ بواسطة‬readLog ‫ثم اضفنا إجراء آخر للقراءة أسميناه‬
:‫ فتتم إضافته بالشكل التالي‬.‫ فقط مخرجات في شكل مقطع‬،‫تكون له مدخلت‬

@WebMethod(operationName = "readLog")
public String readLog() {
//TODO write your implementation code here:
return null;
}
:‫ثم قمنا بكتابة إجراء القراءة من ملف نصي ﻹرجاع الملف كاملا في متغير مقطعي بدلا من عرضه على الشاشة‬
private String readTextFile(String aFileName)
{
try{
BufferedReader reader = new BufferedReader(new FileReader(aFileName));

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫;"" = ‪String contents‬‬
‫;)(‪String line = reader.readLine‬‬

‫{ )‪while (line != null‬‬


‫;)"‪contents = contents.concat(line + "\n‬‬
‫;)(‪line = reader.readLine‬‬

‫}‬

‫;)(‪reader.close‬‬

‫;)‪return (contents‬‬

‫}‬
‫)‪catch (Exception e‬‬
‫{‬
‫;)(‪lastError = e.getMessage‬‬
‫‪return (null); // fail‬‬
‫}‬

‫}‬
‫قمنا بنداء القراءة من الملف النصي في اﻹجراء ‪ readLog‬بالشكل التالي‪:‬‬

‫)"‪@WebMethod(operationName = "readLog‬‬
‫{ )(‪public String readLog‬‬

‫;)"‪String filetext = readTextFile("/tmp/mylog.txt‬‬


‫;‪return filetext‬‬
‫}‬
‫وفي النهاية قمنا بكتابة إجراء ﻹرجاع آخر خطأ حدث وأسميناه ‪:getLastError‬‬

‫)"‪@WebMethod(operationName = "getLastError‬‬
‫{ )(‪public String getLastError‬‬
‫‪//TODO write your implementation code here:‬‬
‫;‪return lastError‬‬
‫}‬
‫حيث يستخدمه العميل لمعرفة الخطأ الذي حدث في خدمة الويب أثناء ندائها‪.‬‬
‫نلحظ أنه لبد أن نستخدم دليل به صلحية للمستخدم ‪ tomcat6‬أو ‪ tomcat7‬والذي يتم إستخدامه مع نظام‬
‫الشغيل عند التعامل مع خدمات الويب‪ .‬وفي هذا المثال السابق استخدمنا الدليل ‪ /tmp‬بإعتبار أن به صلحية‬
‫لكافة المستخدمين في بيئة لينكس‪.‬‬

‫في الواقع العملي تكون إجراءات خدمة الويب مرتبطة بتنفيذ إجراءات في قواعد بيانات مثلا إدخال قيد‬
‫محاسبي‪ ،‬إدراج معاملة بنكية‪ ،‬دفع فاتورة هاتف‪ .‬كذلك ييمكن أن تقوم خدمات الويب بنداء خدمات ويب أخرى‪،‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫فيصبح المعمارية ذات أربع طبقات‪ :‬عميل – خدمة ويب – خدمة ويب أخرى – قاعدة بيانات‪.‬‬

‫بعد ذلك ييمكن تشغيل البرنامج فيتم فتح متصفح الويب تلقائياا لتظهر الشاشة التالية‪:‬‬

‫بعد نهاية عنوان الويب نقوم بإضافة إسم خدمة الويب ‪ Mylog‬لييصبح العنوان هو‪:‬‬
‫‪http://localhost:8080/logfle/Mylog‬‬
‫فيظهر لنا معلومات خدمة الويب ‪:Mylog‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫وعند الضغط على عنوان الـ ‪ WSDL‬يظهر لنا ملف ‪ XML‬وهو وصف لخدمة الويب وييستخدم عند عمل البرامج‬
‫العميلة لخدمات الويب‪:‬‬

‫بذا نكون قد إنتهينا من كتابة وتشغيل خدمة الويب في مخدم ‪.Tomcat‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫وهذا هو رابط الـ ‪:WSDL‬‬

‫‪http://localhost:8080/logfile/Mylog?wsdl‬‬
‫وهذا هو الشيء الوحيد الذي يحتاجه المبرمج لكتابة برنامج عميل ﻹستخدام خدمة الويب‪ .‬ويمكن أن يقوم‬
‫بإستخدام أي لغة برمجة تدعم تقنية الـ ‪ SOAP‬لنداء الدالتين ‪ insertLog‬و ‪.readLog‬‬

‫برنامج عميل خدمة ويب‬


‫ييمكن أن يكون إجراء نداء خدمة الويب في أن نوع من البرامج‪ ،‬مثلا ييمكن أن يكون في برنامج سطح مكتب‬
‫‪ Desktop application‬أو برنامج ويب أو حتى برنامج سطر اﻷوامر كما في مثالنا التالي‪.‬‬
‫نقوم بإنشاء برنامج جديد من نوع ‪ Java/Java application‬ينسميه ‪.calllog‬‬
‫بعدها نجد أن يهناك حزمة اسمها ‪ calllog‬في البرنامج‪ .‬نقوم بإضافة عميل خدمة ويب بواسطة ‪new Web‬‬
‫‪ service client‬فيظهر لنا الفورم التالي‪:‬‬

‫حيث نختار ‪ WSDL URL‬نضع فيه عنوان الـ ‪ WSDL‬لخدمة الويب‪ .‬ثم نختار الحزمة ‪ calllog‬في ‪ Package‬ثم‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


Finish ‫نضغط الزر‬

‫ ونختار‬main ‫ فنقوم بالضغط بالزر اليمين للماوس داخل اﻹجراء‬calllog.java ‫نرجع لملف الكود الرئيسي‬
:‫ كما في الصورة التالية‬Call Web Service Operation ‫ ثم‬Insert Code

:insertLog ‫ثم إختيار‬

:‫فيتم إضافة إجراء جديد لنداء خدمة الويب بالشكل التالي‬

private static Boolean insertLog(java.lang.String text) {


calllog.Mylog_Service service = new calllog.Mylog_Service();
calllog.Mylog port = service.getMylogPort();

Code.sd ‫كود لبرمجيات الكبيوتر‬


return port.insertLog(text);
}
:readLog ‫ونكرر نفس العملية السابقة ﻹضافة نداء اﻹجراء‬

private static String readLog() {


calllog.Mylog_Service service = new calllog.Mylog_Service();
calllog.Mylog port = service.getMylogPort();
return port.readLog();
}

:‫ثم قمنا بتعديلهما ﻹضافة إظهار الخطأ الذي يحدث في خدمة الويب‬

private static Boolean insertLog(java.lang.String text) {


calllog.Mylog_Service service = new calllog.Mylog_Service();
calllog.Mylog port = service.getMylogPort();
boolean res = port.insertLog(text);
if (!res)
System.out.println("Error: " + port.getLastError());
return(res);

private static String readLog() {


calllog.Mylog_Service service = new calllog.Mylog_Service();
calllog.Mylog port = service.getMylogPort();
String result = port.readLog();
if (result == null) {
System.out.println("Error: " + port.getLastError());
}
return (result);
}
:‫ثم قمنا بنداء اﻹجرائين في الدالة الرئيسية للبرنامج‬

public static void main(String[] args) {

Date today = new Date();


insertLog(today.toString() + ": Sample text\n");
String result = readLog();
System.out.print(result);

}
:‫عند تشغيل البرنامج نتحصل على الخرج التالي‬

Fri Mar 29 12:34:48 EAT 2013: Sample text


Fri Mar 29 12:34:53 EAT 2013: Sample text

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫عند تنفيذ أي من اﻹجراءات في الجهاز العميل فإنه يتم تنفيذه في المخدم‪.‬‬
‫وفي الواقع تكون خدمة الويب في جهاز منفصل والبرنامج العميل يكون متصلا به عبر شبكة محلية أو شبكة‬
‫اﻹنترنت‪ ،‬وكل تعقيدات اﻹتصلت بقواعد البيانات يكون في جهة خدمة الويب‪ ،‬ويكون برنامج العميل مبسطاا‬
‫بقدر اﻹمكان لتحقيق فوائد معمارية تعدد الطبقات‪.‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


HTTP ‫القراءة من مخدم ويب بواسطة‬
‫من اسهل الطرق للتصال أو الحصول على معلومة من برنامج أو مخدم في النت أو مخدم داخلي هو استخدام‬
‫ فإن وسيلة اﻹتصال بين العميل والمخدم هو‬SOAP ‫ وكما فعلنا سابقاا باستخدام بروتوكل الـ‬.HTTP ‫بروتوكول الـ‬
‫ في لغة جافا للقراءة من‬HTTP ‫ يمكن استخدام الـ‬.TCP/IP ‫ والذي يعمل فوق بروتوكول الـ‬HTTP ‫بروتوكول الـ‬
.POST ‫ أو ارسال بيانات إلى اليمخدم باستخدام‬GET ‫رابط معين عن طريق‬
:‫ والتي تقوم بالتجهيز للتصال ولكنها ل تقوم باﻹتصال الفعلي‬URL ‫قمنا باستخدام الفئة‬
URL url = new URL(myURL);

‫ والتي تقوم باﻹتصال الفعلي وإرسال واستقبال‬URLConnection ‫ كيمدخل لكائن من فئة‬url ‫ثم تمرير الكائن‬
:‫البيانات‬
URLConnection myURLConnection = url.openConnection();
myURLConnection.connect();

:‫ وذلك بتهيئته من الكائن السابق للتصال‬InputStreamReader ‫ثم تعريف كائن للقراءة من نوع‬
InputStreamReader reader;
reader = new InputStreamReader(myURLConnection.getInputStream());

:‫ وهذا هو كود اﻹجراء كاملا‬.outputResult ‫ وتخزينه في المتغير المقطعي‬،‫ثم قراءة المحتويات من اﻹتصال‬

public static String callURL(String myURL) {


try {

URL url = new URL(myURL);


URLConnection myURLConnection = url.openConnection();
myURLConnection.connect();

InputStreamReader reader;
reader = new InputStreamReader(myURLConnection.getInputStream());

String outputResult= "";


char buf[] = new char[1024];
int len;
while ((len = reader.read(buf)) != ­1){
String data = new String(buf, 0, len);
outputResult = outputResult + data;
}

reader.close();

return(outputResult);

} catch (Exception ex) {

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫;))(‪return("error: " + ex.toString‬‬
‫}‬
‫}‬

‫ويمكن نداء هذا اﻹجراء لقراءة محتويات صفحة كالتالي‪:‬‬

‫;)"‪String content = callURL("http://localhost‬‬


‫;)‪System.out.println(content‬‬

‫يمكن استخدام هذه الطريقة للربط بين برنامجين بطريقة أكثر بساطة من بروتوكول الـ ‪ SOAP‬حيث يمكن أن‬
‫يكون المخدم هو برنامج ويب يحتوي على ‪ Servlet‬يقوم باستقبال معلومات عن طريق ‪ GET‬ويمكن ندائه‬
‫كالتالي‪:‬‬

‫= ‪String content‬‬
‫;)"‪callURL("http://localhost:8080/JavaWebApp/GetCustomerInfo?customerid=1‬‬
‫;)‪System.out.println(content‬‬

‫وفي جانب الـ ‪ Servlet‬يقوم بقراءة المدخلت كالتالي‪:‬‬


‫;)"‪String id = request.getParameter("customerid‬‬

‫ثم يقوم بتنفيذ كود معين‪ ،‬مثلا قراءة معلومات من قاعدة بيانات ثم إرجاعها في شكل ‪ JSON‬أو حتى ‪.XML‬‬
‫وهذه الطريقة يمكن استخدامها لتبادل البيانات بين برنامج أندرويد في الهاتف مع مخدم في النترنت‪ .‬ويمكن‬
‫تحويل تلك الطريقة قليلا )ارسال المعلومات باستخدام ‪ POST‬في شكل ‪ JSON‬بدلا من إرسالها في شكل مدخلت‬
‫‪ parameters‬لتصبح بروتوكول ‪ REST‬أو ما ييسمى بالـ ‪.RESTFull‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫خدمات ويب الـ ‪RESTFull‬‬

‫كما ذكرنا في المثال السابق لقراءة معلومة من برنامج ‪ web‬باستخدام الـ ‪ ،URL‬وقلنا أنها طريقة بسيطة لعمل‬
‫خدمة ويب‪ .‬وخدمات الويب مشابهة تمام اا في البروتوكول والتقنيات مع برامج الويب‪ ،‬حيث أن التقنية‬
‫المستخدمة في برامج الويب ييمكن استخدامها في برامج الويب‪ .‬أما اﻹختلفات فتكمن في التي‪:‬‬

‫‪ .1‬المستخدم المباشر لبرامج الويب هو شخص يستخدم المتصفح لستعراض والتفاعل مع البرنامج‪ ،‬أما من‬
‫يستخدم خدمة الويب فهو برنامج آخر وليس إنسان‪.‬‬
‫‪ .2‬الرد الذي يرجع من برنامج الويب يكون في شكل ‪ HTML‬حتى يستطيع المتصفح فهمه وعرضه بالشكل‬
‫المطلوب للمستخدم النهائي‪ ،‬أما خدمات الويب فيكون الرد الذي ينتج عن نداء خدمة ويب أو إجراء فيها‬
‫هو هيكل بيانات متفق عليه بين خدمة الويب والبرنامج المستفيد منها‪ ،‬مثل أن تكون في شكل ‪ XML‬أو‬
‫‪ JSON‬أو بيانات في شكل خصائص‪ ،‬حيث أن طريقة إظهار المعلومة وشكل الفورم النهائي ليس له علقة‬
‫بخدمة الويب‪ ،‬وإنما هو مسؤولية البرنامج العميل‪ ،‬و يمكن أن يكون عبارة عن برنامج ذو واجهة رسومية‪،‬‬
‫مثل برنامج الـ ‪.Swing‬‬

‫أما وجه الشبه بينها فيتمثل في‪:‬‬

‫‪ .1‬كلهما يستخدم بروتوكول الـ ‪ HTTP‬لتبادل البيانات بين المخدم والعميل‬


‫‪ .2‬يمكن ان يشتركا في نفس تقنية الويب‪ ،‬مثلا في لغة جافا ييمكننا استخدام ‪ JSP‬أو ‪ ،Servlet‬لكن بالنسبة‬
‫لخدمات الويب فبما أنها ل تستخدم ‪ HTML‬فاﻷفضل إذاا استخدام تقنية الـ ‪.Servlet‬‬
‫‪ .3‬كلهما تتم استضافته في نفس مخدم الويب مثل ‪ Tomcat‬وهذا مرتبط بالتقنية المستخدمة حيث أنها‬
‫تتطلب هذا النوع من مخدمات الويب والذي ييسمى أحياناا حاوية البرامج ‪.container‬‬

‫لعمل خدمة ويب من نوع الـ ‪ RESTFull‬يمكننا إضافة ‪ Servlet‬جديد في برنامج ويب جديد أو في برامج قديم‪،‬‬
‫حيث يمكن لبرنامج ويب واحد أن يحتوي على خدمات ويب من نوع ‪ SOAP‬و ‪ RESTFull‬وحتى صفحات ويب‪،‬‬
‫لكن اﻷفضل أن يكون يهناك برنامج ويب منفصل لكل تقنية ﻷن كل واحدة يمكن أن تتطلب مكتبات مختلفة‪ ،‬كذلك‬
‫فإن اﻷفضل دائم اا عزل أنواع البرامج لتكون متخصصة في خدمة ما حتى تسهل صيانتها‪ ،‬وتشغيلها‪ ،‬وتطويرها‪.‬‬
‫قمنا بعمل برنامج ويب اسميناه ‪ ،RESTServer‬ثم اضفنا خدمة ويب بتقنية ‪ Servlet‬اسميناها ‪.GetServerInfo‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ومهمتها هي إرجاع بعض المعلومات عن المخدم‪ ،‬مثل نوع نظام التشغيل و تاريخ المخدم وينسخة جافا‪ ،‬وذلك في‬
‫شكل بيانات من نوع الخصائص ‪ Properties‬بالشكل التالي‪:‬‬

‫‪protected void processRequest(HttpServletRequest request, HttpServletResponse‬‬


‫)‪response‬‬
‫{ ‪throws ServletException, IOException‬‬
‫;)"‪response.setContentType("text/html;charset=UTF­8‬‬
‫{ ))(‪try (PrintWriter out = response.getWriter‬‬

‫;)"‪String os = System.getProperty("os.name‬‬
‫;)(‪Date now = new Date‬‬
‫;)"‪String java = System.getProperty("java.version‬‬
‫;)"‪out.println("OS=" + os + "\n‬‬
‫;)"‪out.println("time=" + now.toString() + "\n‬‬
‫;)‪out.println("javaversion=" + java‬‬
‫}‬
‫}‬

‫بعد ذلك نقوم بتشغيل البرنامج لعرضه في المتصفح وإضافة إسم خدمة الويب ‪ GetServerInfo‬إلى العنوان‬
‫ليصبح كالتالي‪:‬‬
‫‪http://localhost:8084/RESTServer/GetServerInfo‬‬

‫فيكون الرد كالتالي في المتصفح‪:‬‬

‫نلحظ أن البيانات ظهرت في سطر واحد‪ ،‬حيث أننا لم نستخدم نسق الـ ‪ HTML‬حتى تظهر بصورة جيدة‪ ،‬وكما‬
‫ذكرنا فإن المقصود ليس المتصفح وإنما برنامج آخر تتم كتابته بواسطة المبرمج‪ ،‬لكن يمكن استخدام المتصفح‬
‫أثناء تطوير البرنامج ﻷجل عرض البرامج‪ .‬يمكن عرضه بطريقة أفضل بعرض مصدر الصفحة من المتصفح‬
‫وذلك بالضغط بالزر اليمين على الصفحة ثم اختيار ‪ View page source‬ليظهر لنا النص كما جاء من المخدم‬
‫بدون تغيير‪:‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ايض اا يمكننا استخدام بعض اﻷدوات البسيطة التي تقوم بعرض صفحة ويب في الطرفية مثل برنامج ‪ curl‬في‬
‫نظام لينكس‪:‬‬

‫كذلك يمكننا عمل برنامج يقرأ الـ ‪ URL‬كما كتبنا سابقاا‪ ،‬يمكننا نداء اﻹجراء التي كتبناه سابقاا ‪.callURL‬‬
‫قمنا بعمل برنامج ‪ Java Application‬جديد اسميناه ‪ CallRest‬واضنا إليه اﻹجراء ‪ callURL‬ثم قمنا بندائه في‬
‫اﻹجراء ‪ main‬كالتالي‪:‬‬

‫;)"‪String content = callURL("http://localhost:8084/RESTServer/GetServerInfo‬‬


‫;)‪System.out.println(content‬‬

‫فكانت النتيجة‪:‬‬
‫‪OS=Linux‬‬
‫‪time=Sat Sep 03 11:42:41 EAT 2016‬‬
‫‪javaversion=1.7.0_111‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ لذلك‬،‫لكن فإن البرنامج العميل ل يريد مجرد إظهار المعلومات وإنما معالجتها مثلا وقراءة كل قيمة بمفردها‬
:‫نستخدم كائن الخصائص لستخلص تلك القيم التي رجعت من خدمة الويب‬

public static void main(String[] args) throws IOException {


// TODO code application logic here

String content;
content = callURL("http://localhost:8084/RESTServer/GetServerInfo");

// Load output into stream


ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes());

// Parse output
Properties properties = new Properties();
properties.load(in);
String serverOS = properties.getProperty("OS");
String serverTime = properties.getProperty("time");
String javaVersion = properties.getProperty("javaversion");

// Display output
System.out.println("Server OS is : " + serverOS);
System.out.println("Server Time is : " + serverTime);
System.out.println("Server Java version is : " + javaVersion);
}

‫ لقراءة محتويات المقطع الذي يحتوي على الخصائص لتحويلها‬ByteArrayInputStream ‫قمنا باستخدام الفئة‬
‫ وذلك ﻷن كائن الخصائص يستطيع القراءة من سلسلة بيانات ول يستطيع القراءة من‬stream ‫إلى سلسلة بيانات‬
:‫ فكان هذا بمثابة تحويل للية نقل البيانات‬،‫مقطع مباشرة‬
ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes());
Properties properties = new Properties();
properties.load(in);

.‫ لكن نريد إرسال بيانات من العميل إلى المخدم‬،‫في هذا المثال ركزنا على إرجاع بيانات من المخدم إلى العميل‬
‫ وكمثال طلبنا من البرنامج العميل إدخال اسم‬،‫قمنا بتعديل خدمة الويب لقراءة مدخلت من نوع الخصائص‬
:‫الزبون وعنوانه‬
‫ وذلك‬،‫قمنا باستخدام كائنة من فئة الخصائص في المخدم لقراءة المعلومات اليمرسلة بواسطة البرنامج العميل‬
:‫بإضافة هذا الكود‬
// read input
Properties properties = new Properties();
properties.load(request.getInputStream());
String customerName = properties.getProperty("name");
String customerAddress = properties.getProperty("address");

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫ ﻷن البيانات اليمرسلة توجد في شكل سلسلة بيانات ويمكن‬ByteArrayInputStream ‫هذه المرة لم نحتاج للفئة‬
‫استخلص كائن سلسلة البيانات بهذه الطريقة‬
request.getInputStream()

:‫ ليصبح كود خدمة الويب كالتالي‬،‫قمنا كذلك بإرجاع نفس البيانات اليمرسلة‬

protected void processRequest(HttpServletRequest request, HttpServletResponse


response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF­8");
try (PrintWriter out = response.getWriter()) {

// read input
Properties properties = new Properties();
properties.load(request.getInputStream());

String customerName = properties.getProperty("name");


String customerAddress = properties.getProperty("address");

String os = System.getProperty("os.name");
Date now = new Date();
String java = System.getProperty("java.version");
out.println("OS=" + os);
out.println("time=" + now.toString());
out.println("javaversion=" + java);
out.println("customername=" + customerName);
out.println("customeraddress=" + customerAddress);
}
}

‫ ﻷن إرسال البيانات الذي استخدمناه‬،‫هذه المكرة ل يمكننا نداء خدمة الويب هذه عن طريق المتصفح العادي‬
.URL ‫ والتي يتم إرسال البيانات فيها بمعزل عن العنوان‬POST ‫يستخدم طريقة‬
‫ نقوم بإضافة‬Firefox ‫ مثلا في متصفح‬،‫لذلك لتجربة خدمة الويب هذه نحتاج لتثبيت أداة إضافية في المتصفح‬
:‫ وذلك عن طريق‬RESTClient ‫اﻷداة‬
Add-ons/Extensions

‫ بعد ذلك نقوم‬،‫ فتظهر في اعلى المتصفح‬،‫ ثم نعيد تشغيله‬،‫ ثم نضيفها إلى المتصفح‬RESTClient ‫ثم نبحث عن‬
(Method) ‫بإدخال عنوان خدمة الويب ثم كتابة اليمدخلت في شكل خصائص وتحويل طريقة إرسال البيانات‬
:‫ بالشكال التالي‬POST ‫إلى‬

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫وكما ذكرنا سابقاا فإن خدمة الويب ل يتم استخدامها مع المتصفح‪ ،‬لكن هذه اﻷداة يتستخدم أثناء تطوير البرنامج‬
‫بواسطة المبرمج أو من يقوم باختبار خدمة الويب‪ ،‬أما المستخدم النهائي والمستفيد من النظام فل يستخدم هذه‬
‫اﻷدوات‪ ،‬إنما يستخدم البرنامج العميل‪.‬‬
‫بعد ذلك قمنا بتعديل البرنامج العميل ﻹرسال تلك البيانات‪ ،‬وأول تعديل كان للجراء ‪ callURL‬حيث اضفنا له‬
‫يمدخلت‪:‬‬

‫{ )‪public static String callURL(String myURL, String input‬‬

‫ثم اخبار كائن اﻹتصال أن هناك ‪output‬‬


‫;)‪myURLConnection.setDoOutput(true‬‬

‫ثم قمنا بتعريف كائن للكتابة من نوع ‪ OutputStreamWriter‬ﻹرسال تلك البيانات إلى كائن اﻹتصال‪:‬‬

‫;‪OutputStreamWriter writer‬‬
‫;))(‪writer = new OutputStreamWriter(myURLConnection.getOutputStream‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


writer.write(input);
writer.flush();
writer.close();

:‫ ثم إرجاع النتيجة‬POST ‫ والذي يقوم بإرسال بيانات في شكل‬callURL ‫فكان هذا هو الشكل النهائي للجراء‬

public static String callURL(String myURL, String input) {


try {

URL url = new URL(myURL);


URLConnection myURLConnection = url.openConnection();
myURLConnection.setDoOutput(true);
myURLConnection.connect();

// Write Input
OutputStreamWriter writer;
writer = new OutputStreamWriter(myURLConnection.getOutputStream());
writer.write(input);
writer.flush();
writer.close();

// Read result
InputStreamReader reader;
reader = new InputStreamReader(myURLConnection.getInputStream());

String outputResult= "";


char buf[] = new char[1024];
int len;
while ((len = reader.read(buf)) != ­1){
String data = new String(buf, 0, len);
outputResult = outputResult + data;
}

reader.close();

return(outputResult);

} catch (Exception ex) {


return("error: " + ex.toString());
}
}

:‫ كالتالي‬main ‫ثم قمنا بالنداء في اﻹجراء‬

String input;
input = "name=Motaz Abdel Azeem\naddress=Khartoum, Sudan";

String content;
content = callURL("http://localhost:8084/RESTServer/GetServerInfo", input);

Code.sd ‫كود لبرمجيات الكبيوتر‬


:‫ وهذا هو كود النداء كاملا‬.‫ويمكن استخدام كائن الخصائص بدلا من كتابة كافة اليمدخلت في سطر واحد‬

public static void main(String[] args) throws IOException {


// TODO code application logic here

String input;
input = "name=Motaz Abdel Azeem\naddress=Khartoum, Sudan";

String content;
content = callURL("http://localhost:8084/RESTServer/GetServerInfo", input);

// Load output into stream


ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes());

// Prase output
Properties properties = new Properties();
properties.load(in);
String serverOS = properties.getProperty("OS");
String serverTime = properties.getProperty("time");
String javaVersion = properties.getProperty("javaversion");
String customerName = properties.getProperty("customername");
String customerAddress = properties.getProperty("customeraddress");

// Display output
System.out.println("Server OS is : " + serverOS);
System.out.println("Server Time is : " + serverTime);
System.out.println("Server Java version is : " + javaVersion);
System.out.println("Customer name : " + customerName);
System.out.println("Customer address : " + customerAddress);
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫استخدام نسق ‪JSON‬‬
‫نسق الـ ‪ JSON‬هو بديل لنسق الـ ‪ ،XML‬فهو اسهل كتابة وأقل حجماا من الـ ‪ .XML‬وهو مناسب للستخدام لنقل‬
‫البيانات في خدمات الويب‪ ،‬وهو يسمح بنقل بيانات أكثر تعقيداا مثل المصفوفات )مقارنة بنوع الخصائص(‪ .‬لكن‬
‫قبل استخدامه في خدمات الويب‪ ،‬لبد من البحث عن مكتبة تدعم هذا النسق لستخدامها مع برامج جافا التي‬
‫تحاج إليه‪.‬‬
‫المكتبة التي استخدمناها اسمها ‪ json-simple‬وهذا مثال ﻹسم ملف يمكن الحصول عيه من النت‪:‬‬
‫‪json­simple­1.1.jar‬‬

‫لشرحها أو ا‬
‫ل قبل استخدامها في خدمات الويب‪ ،‬قمنا بعمل برنامج جافا عادي ثم اضفنا هذه المكتبة في جزء‬
‫‪ library‬بواسطة ‪ Add JAR/Folder‬ثم قمنا بكتابة هذا الكود لكتابة بيانات في شكل ‪:JSON‬‬
‫;)(‪JSONObject myObject = new JSONObject‬‬
‫;)‪myObject.put("year", 2016‬‬
‫;)"‪myObject.put("service", "Customer Registration‬‬
‫;)‪myObject.put("valid", true‬‬
‫;))(‪System.out.println(myObject.toJSONString‬‬

‫في هذا المثال استخدمنا كائن من نوع الفئة ‪ JSONObject‬للتعامل مع هذه النوعية من النسق‪.‬‬
‫وناتج التشغيل هو مقطع في شكل ‪:JSON‬‬
‫}‪{"valid":true,"service":"Customer Registration","year":2016‬‬

‫بعد إضافة كافة العناصر باستخدام ‪ put‬نقوم في النهاية بالحصول على المقطع الذي يحتوي على هذا النسق‬
‫بواسطة ‪.toJSONSting‬‬
‫وهذا الجزء ييستخدم في جانب العميل ﻹرسال بيانات في شكل ‪ ،JSON‬أما المخدم فيقوم بمعالجة هذه المعلومات‬
‫واستخلص القيم بواسطة أسماءها‪ .‬قمنا بإضافة هذا الكود في نفس البرنامج لمعرفة آلية قراءة مقطع ‪JSON‬‬
‫وتحويله إلى متغيرات بسيطة‪:‬‬

‫;)(‪String myInput = myObject.toJSONString‬‬


‫;)(‪JSONParser parser = new JSONParser‬‬
‫;)‪JSONObject received = (JSONObject)parser.parse(myInput‬‬
‫;))(‪System.out.println("year is: " + received.get("year").toString‬‬
‫;))(‪System.out.println("service is: " + received.get("service").toString‬‬
‫;))(‪System.out.println("Is valid: " + received.get("valid").toString‬‬

‫هذه المرة استخدمنا كائن من النوع ‪ JSONParser‬لتحويل المقطع إلى كائن ‪ JSON‬حتى نتعامل مع البيانات التي‬
‫بداخله مباشرة‪ ،‬وفي هذا السطر يتم تحويل المقطع إلى ‪:JSON‬‬
‫;)‪JSONObject received = (JSONObject)parser.parse(myInput‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬


‫ في هذا‬،‫ والتي تقوم بالتحويل من نوع بيانات أو كائنات إلى اخرى‬casting ‫نلحظ أننا استخدمنا ما ييعرف بالـ‬
.JSONObject ‫ إلى‬object ‫المثال تقوم بتحويل نوع الكائن‬
‫ وتحويلها إلى صيغتها‬received ‫ لقراءة البيانات الموجودة في الكائن‬،‫بعد ذلك قمنا بمحاكاة جزئية المخدم‬
‫ التحويل إلى الصيغ البسيطة يمكن بهذه الطريقة بدلا من قراءتها‬.‫ أو الرقمية أو المنطقية‬،‫البسيطة المقطعية‬
:‫جميعها كأنها مقاطع‬

int year = Integer.parseInt(received.get("year").toString());


boolean isValid = Boolean.valueOf(received.get("valid").toString());

.‫ بدلا من نوع الخصائص‬JSON ‫ ليستقبل بيانات من نوع‬RESTServer ‫بعد ذلك قمنا بتحويل البرنامج‬
:JSON ‫ وهو مقطع الـ‬،‫أولا اضفنا إجراء جديد لقراءة المحتويات اليمرسلة وتحويلها إلى مقطع واحد‬

public static String readClient(HttpServletRequest request) throws IOException


{
BufferedReader reader = request.getReader();
String line;
String jsonText = "";
while ((line = reader.readLine()) != null){
jsonText = jsonText + line;
}
return jsonText;
}

:‫وهذا هو الجزء الذي نقوم فيه باستقبال ثم معالجة اليمدخلت وتحويلها إلى بيانات بسيطة‬

String requestStr = readClient(request);

JSONParser parser = new JSONParser();


JSONObject obj = (JSONObject) parser.parse(requestStr);
String customerName = obj.get("name").toString();
String customerAddress = obj.get("address").toString();

:‫ ايضاا كالتالي‬JSON ‫ثم قمنا بإرجاع الرد في شكل‬


JSONObject result = new JSONObject();
result.put("success", true);
result.put("OS", os);
result.put("time", now.toString());
result.put("javaversion", java);
result.put("customername", customerName);
result.put("customeraddress", customerAddress);
out.println(result.toJSONString());

Code.sd ‫كود لبرمجيات الكبيوتر‬


:‫ هو التالي‬GetServiceInfo ‫والكود الكامل لخدمة الويب‬

protected void processRequest(HttpServletRequest request, HttpServletResponse


response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF­8");
response.setCharacterEncoding("UTF­8");
try (PrintWriter out = response.getWriter()) {

try {
// read input
String requestStr = readClient(request);

JSONParser parser = new JSONParser();


JSONObject obj = (JSONObject) parser.parse(requestStr);
String customerName = obj.get("name").toString();
String customerAddress = obj.get("address").toString();

String os = System.getProperty("os.name");
Date now = new Date();
String java = System.getProperty("java.version");

// prepare output
JSONObject result = new JSONObject();
result.put("success", true);
result.put("OS", os);
result.put("time", now.toString());
result.put("javaversion", java);
result.put("customername", customerName);
result.put("customeraddress", customerAddress);

// Write output
out.println(result.toJSONString());
}
catch (Exception ex){
JSONObject obj = new JSONObject();
obj.put("success", false);
obj.put("error", ex.toString());
out.println(obj.toJSONString());
}
}
}

JSON ‫ بإرسال اليمدخلت في شكل نسق‬Firefox ‫ في متصفح‬RESTClient ‫يمكن مناداته باستخدام اﻷداة‬
:‫كالمثال التالي‬
{"name":"‫"معتز عبدالعظيم‬,
"address":"Khartoum, Sudan"}

Code.sd ‫كود لبرمجيات الكبيوتر‬


:‫ كالتالي‬JSON ‫ليظهر لنا الرد في شكل‬

‫ ثم تحويل اليمدخلت لشكل‬json-simple ‫( فنقوم ايضاا بإضافة المكتبة‬CallRest ‫أما في جزئية العميل )برنامج‬
.JSON
:‫ كالتالي‬callURL ‫ في اﻹجراء‬UTF-8 ‫ثم قمنا بإضافة ﻹظهار اللغة العربية لتحويل البيانات إلى‬

URL url = new URL(myURL);


URLConnection myURLConnection = url.openConnection();
myURLConnection.setDoOutput(true);
myURLConnection.setRequestProperty("content­type",
"text/json; charset=utf­8");
myURLConnection.connect();

:‫ثم نداءه بهذه الطريقة‬


JSONObject input = new JSONObject();
input.put("name", "‫;)"معتز عبدالعظيم‬
input.put("address", "‫;)"السودان ­ الخرطوم‬

String content;

Code.sd ‫كود لبرمجيات الكبيوتر‬


content = callURL("http://localhost:8084/RESTServer/GetServerInfo",
input.toJSONString());
System.out.println(content);
:JSON ‫فتكون النتيجة هي مقطع في نسق‬
{"time":"Sat Sep 03 14:23:59 EAT
2016","javaversion":"1.7.0_111","OS":"Linux","customeraddress":" ­ ‫السودان‬
‫"الخرطوم‬,"success":true,"customername":"‫}"معتز عبدالعظيم‬

:‫ويمكننا كذلك معالجة هذه النتيجة للتعامل معها كبيانات بسيطة‬


JSONParser parser = new JSONParser();
JSONObject outputResult = (JSONObject) parser.parse(content);

String serverOS = outputResult.get("OS").toString();


String serverTime = outputResult.get("time").toString();
String javaVersion = outputResult.get("javaversion").toString();
String customerName = outputResult.get("customername").toString();
String customerAddress = outputResult.get("customeraddress").toString();

false ‫ أما إذا كانت‬،‫ قمنا بقراءة باقي القيم‬true ‫ فإذا كانت تحتوي على‬success ‫لكن علينا أولا قراءة القيمة‬
:error ‫فنقوم بإظهار الخطأ‬
JSONParser parser = new JSONParser();
JSONObject outputResult = (JSONObject) parser.parse(content);
boolean success = Boolean.valueOf(outputResult.get("success").toString());

if (success){
String serverOS = outputResult.get("OS").toString();
String serverTime = outputResult.get("time").toString();
String javaVersion = outputResult.get("javaversion").toString();
String customerName = outputResult.get("customername").toString();
String customerAddress =
outputResult.get("customeraddress").toString();

// Display output
System.out.println("Server OS is : " + serverOS);
System.out.println("Server Time is : " + serverTime);
System.out.println("Server Java version is : " + javaVersion);
System.out.println("Customer name : " + customerName);
System.out.println("Customer address : " + customerAddress);
}
else
{
System.out.println("Error: " + outputResult.get("error").toString());
}

Code.sd ‫كود لبرمجيات الكبيوتر‬


‫وفي الختام نتمنى أن يتنال الفائدة من هذا الكتاب‪.‬‬

‫ملوحظة‪:‬‬
‫هذا الكتاب مازال يتم تعديله من فترة ﻷخرى‪ ،‬فنرجو الحرص على الحصول على آخر ينسخة من الموقع‪.‬‬

‫معتز عبدالعظيم الطاهر‬


‫كود لبرمجيات الكمبيوتر‬
‫‪code.sd‬‬

‫كود لبرمجيات الكبيوتر ‪Code.sd‬‬

You might also like