CodeGym /مدونة جافا /Random-AR /القراءة من لوحة المفاتيح: "القراء"
John Squirrels
مستوى
San Francisco

القراءة من لوحة المفاتيح: "القراء"

نشرت في المجموعة
أهلاً! علمتك الدروس والمهام في المستوى 3 كيفية عرض الأشياء على وحدة التحكم، والتحرك في الاتجاه الآخر، كيفية قراءة البيانات من لوحة المفاتيح.
القراءة من لوحة المفاتيح: "القراء" - 1
لقد تعلمت أيضًا استخدام البنية المعقدة التالية لإنجاز ذلك:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
ولكن هناك سؤال واحد لم نجيب عليه بعد.

كيف يعمل هذا في العالم؟

في الواقع، نادرًا ما تكون البرامج مستقلة تمامًا. يتواصلون مع البرامج والأنظمة الأخرى والإنترنت وما إلى ذلك. ونعني بكلمة "التواصل" بشكل أساسي "تبادل البيانات". أي أنهم يتلقون بعض البيانات الخارجية ويرسلون أيضًا بيانات البرنامج الداخلية إلى مكان ما. تكثر الأمثلة على برامج تبادل البيانات في الحياة اليومية. على سبيل المثال، تتيح لك العديد من مواقع الويب تسجيل الدخول باستخدام حسابك على Facebook أو Twitter بدلاً من التسجيل. في هذه الحالة، يقوم برنامجان (مثل Twitter وموقع الويب الذي تقوم بتسجيل الدخول إليه) بتبادل البيانات الضرورية. والنتيجة النهائية هي أنك قمت بتسجيل الدخول بنجاح. يتم استخدام كلمة "دفق" لوصف عملية تبادل البيانات. من أين جاء هذا الاسم؟ من خلال تجربتك، قد يكون "التدفق" مرتبطًا بالأنهار أكثر من ارتباطه بالبرمجة. هذا ليس من قبيل الصدفة :) الدفق هو، في جوهره، قطعة متحركة من البيانات. بمعنى آخر، في البرمجة، ليس الماء هو الذي يتدفق، بل البيانات في شكل بايتات وأحرف. يمكننا تلقي أجزاء من البيانات من دفق البيانات ثم استخدامها. مرة أخرى، سوف نستخدم تشبيه الماء/التدفق: يمكنك جمع الماء من النهر لصنع الحساء، أو إطفاء النار، أو سقي زهورك. تتيح لك التدفقات العمل مع أي مصدر بيانات: سواء كان الإنترنت أو نظام الملفات بجهاز الكمبيوتر الخاص بك أو أي شيء آخر - فلا فرق. التدفقات هي أداة عالمية. إنها تسمح للبرنامج بتلقي البيانات من أي مكان (تدفقات الإدخال) وإرسالها إلى أي مكان (تدفقات الإخراج). مهمتهم هي نفسها: أخذ البيانات من مكان وإرسالها إلى مكان آخر. هناك نوعان من التدفقات:
  1. يتم استخدام تدفقات الإدخال لتلقي البيانات
  2. تدفقات الإخراج مخصصة لإرسال البيانات.
في Java، يتم تنفيذ هذه التدفقات بواسطة InputStreamالفئتين OutputStream. ولكن يمكن تصنيف التدفقات بطريقة أخرى. بالإضافة إلى تدفقات الإدخال والإخراج، فإننا نتحدث أيضًا عن تدفقات البايت وتدفقات الأحرف . يجب أن يكون المعنى هنا واضحًا بدرجة كافية: يرسل دفق البايت المعلومات كمجموعة من البايتات، بينما يرسلها دفق الأحرف كمجموعة من الأحرف. في هذا الدرس، سنتناول تدفقات الإدخال. سأضع رابطًا يحتوي على معلومات حول تدفقات الإخراج في نهاية الدرس. يمكنك قراءتها بنفسك :) ألقِ نظرة الآن على هذا الرمز:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
أثناء متابعة الدروس، ألا تعتقد أن هذا الخط كان مخيفًا إلى حد ما؟ :) لن يكون هذا هو الحال بمجرد استكشافنا لكيفية عمله. دعونا نضع الأمور في نصابها الصحيح. سنبدأ في النهاية. System.inهو InputStreamكائن، مثال للفئة التي تحدثنا عنها في وقت سابق. وهو عبارة عن دفق إدخال مرتبط بجهاز إدخال النظام (لوحة المفاتيح). بالمناسبة، أنت على دراية بهذا الدفق بشكل غير مباشر. بعد كل شيء، كثيرًا ما تستخدم "زميل العمل" — System.out! هو دفق إخراجSystem.out النظام . يتم استخدامه لإخراج البيانات إلى وحدة التحكم عبر طريقتك المفضلة ، والتي تستخدمها باستمرار :) وهو عبارة عن دفق لإرسال البيانات إلى وحدة التحكم، بينما يتم استخدامه للحصول على البيانات من لوحة المفاتيح. الأمر كله بسيط :) علاوة على ذلك، يمكننا قراءة البيانات من لوحة المفاتيح بدون هذا البناء الضخم. يمكننا ببساطة أن نكتب: ; System.out.println()System.outSystem.inSystem.in.read()
public class Main {

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

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
الفئة InputStream(تذكر System.inأنها InputStreamكائن) لديها read()طريقة تتيح لك قراءة البيانات. هناك مشكلة واحدة: يقرأ البايتات وليس الأحرف . من الممل استخدام الحروف الإنجليزية فقط، لذا دعونا نحاول قراءة الحرف الصيني "魚" من لوحة المفاتيح (فقط انسخ هذا الحرف من هنا والصقه على وحدة التحكم باستخدام ctrl + v على الكمبيوتر الشخصي أو Command + v على Mac). بالمناسبة، هذه الشخصية تعني "سمكة". إخراج وحدة التحكم: 233 173 154 10 يشغل هذا الرمز والعديد من الرموز الصينية الأخرى 3 بايت في ذاكرة الكمبيوتر (على عكس الحروف اللاتينية، التي تشغل بايتًا واحدًا فقط). في هذه الحالة، تتم قراءة 4 بايتات من الدفق: تمثل الثلاثة الأولى الحرف "魚"، وتمثل البايتات الأخرى سطرًا جديدًا (Enter). وبناء على ذلك، System.inفي شكله غير المزخرف ليس خيارا بالنسبة لنا. البشر (مع استثناءات نادرة!) لا يعرفون كيفية قراءة البايتات. لكن InputStreamReaderالفصل يأتي للإنقاذ! دعونا نرى أي نوع من الحيوانات هذا.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
ننتقل System.inإلى كائن InputStreamReader . اسم الفصل يقول ذلك! نقوم بإنشاء InputStreamReaderكائن وتمريره إلى دفق الإدخال الذي سيقرأ البيانات منه. في هذه الحالة...
new InputStreamReader(System.in)
...نقول لها، "سوف تقرأ البيانات من دفق إدخال النظام (من لوحة المفاتيح)". ولكن هذه ليست وظيفتها الوحيدة! لا InputStreamReaderيتلقى البيانات من الدفق فقط. كما أنه يحول تدفقات البايت إلى تدفقات الأحرف . بمعنى آخر، لم تعد بحاجة إلى تحويل البيانات من "الآحاد والأصفار" إلى "لغة يمكن قراءتها بواسطة الإنسان". InputStreamreaderيفعل كل شيء من أجلك. وبطبيعة الحال، InputStreamReaderلا يقتصر على قراءة البيانات من وحدة التحكم. ويمكنه قراءة البيانات من أماكن أخرى أيضًا. على سبيل المثال، من ملف:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
نقوم هنا بإنشاء FileInputStream(نكهة واحدة لـ InputStream)، وتمرير مسار الملف، وتمرير الدفق نفسه إلى ملف InputStreamReader. الآن سيكون قادرًا على قراءة البيانات من الملف (إذا كان الملف موجودًا بالفعل في المسار بالطبع). نستخدم أيضًا طريقة InputStreamReaderالفصل read()لقراءة البيانات (لا يهم مصدر البيانات: وحدة التحكم، أو الملف، أو أي مكان آخر). ما الفرق بين System.in.read()و InputStreamReader.read()؟\ لنحاول مرة أخرى قراءة الحرف "魚" بامتداد InputStreamReader. أذكرك بما قرأه بالفعل System.in.read(): 233 173 154 10 وكيف يعمل InputStreamReaderنفس الشيء؟
public class Main {

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

       InputStreamReader reader = new InputStreamReader(System.in);
       while (true) {
           int x = reader.read();
           System.out.println(x);
       }
   }
}
إخراج وحدة التحكم: 39770 10 الفرق واضح على الفور. البايت الأخير (الذي يمثل السطر الجديد) يبقى دون تغيير (الرقم 10)، ولكن تم تحويل الحرف "魚" إلى رمز واحد "39770". هذا هو معنى قراءة الشخصيات! إذا كنت لا تعتقد أن 39770 يمثل الحرف "魚"، فمن السهل أن تقنع نفسك :)
import java.io.IOException;

public class Main {

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

       char x = 39770;
       System.out.println(x);
   }
}
مخرجات وحدة التحكم: ولكن إذا كان الأمرInputStreamReader رائعًا جدًا، فلماذا نحتاج إليه أيضًا BufferedReader؟ InputStreamReaderيعرف كيفية قراءة البيانات وتحويل البايتات إلى أحرف. ما الذي يمكن أن نطلبه أكثر من ذلك؟ لماذا قارئ آخر؟ : / الجواب بسيط للغاية: لمزيد من الأداء والراحة . لنبدأ بالأداء. عندما يقرأ البيانات، فإنه يستخدم منطقة خاصة تسمى المخزن المؤقت، حيث "يخزن" الأحرف التي يقرأها. في النهاية، عند الحاجة إلى هذه الأحرف في البرنامج، سيتم أخذها من المخزن المؤقت، وليس مباشرة من مصدر البيانات (لوحة المفاتيح، الملف، وما إلى ذلك). وهذا يوفر الكثير من الموارد. لفهم كيفية عمل ذلك، تخيل ساعيًا في شركة كبيرة. يجلس الساعي في المكتب، في انتظار أن يأتي شخص ما بالطرود للتسليم. في كل مرة يحصل فيها على طرد جديد، يمكنه الانطلاق على الفور. ولكن يمكن أن يكون هناك الكثير من الحزم خلال النهار. سيتعين عليه القيام بالكثير من الرحلات بين المكتب وعناوين التسليم. وبدلاً من ذلك، يضع الساعي صندوقًا في مكتبه. الجميع يضع حزمهم في الصندوق. الآن يمكن للساعي أن يأخذ الصندوق بهدوء وينتقل من عنوان إلى عنوان. وهذا يوفر الكثير من الوقت، لأنه لن يضطر إلى العودة إلى المكتب في كل مرة. في هذا المثال، يعد المربع مجرد مخزن مؤقت، والمكتب هو مصدر بيانات. من الأسهل كثيرًا على شركة التوصيل أن تأخذ الطرود من صندوق واحد عند إجراء عمليات التسليم بدلاً من العودة إلى المكتب في كل مرة. سيوفر البنزين أيضًا. وبالمثل، في البرنامج، يكون أخذ البيانات من المخزن المؤقت أقل استهلاكًا للموارد مقارنةً بالإشارة إلى مصدر البيانات في كل مرة. ونتيجة لذلك، + أسرع من وحده . لقد أخذنا بعين الاعتبار الأداء. ماذا عن الراحة؟ الميزة الرئيسية هي أنه يمكنه قراءة البيانات ليس فقط حرفًا واحدًا في كل مرة (على الرغم من أنه يمكنه فعل ذلك بطريقته )، ولكن أيضًا سطور كاملة في المرة الواحدة! ويتم ذلك باستخدام الطريقة؛ BufferedReaderBufferedReaderInputStreamReaderInputStreamReaderBufferedreaderread()readLine()
public class Main {

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

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String s = reader.readLine();
       System.out.println("We read this line from the keyboard:");
       System.out.println(s);
   }
}
إخراج وحدة التحكم: CodeGym هو أفضل موقع لتعلم Java! نقرأ هذا السطر من لوحة المفاتيح: CodeGym هو أفضل موقع لتعلم Java! وهذا مفيد بشكل خاص عند قراءة كميات كبيرة من البيانات. لا يزال من الممكن قراءة سطر أو سطرين من النص حرفًا بحرف. لكن القراءة في "الحرب والسلام" حرفًا واحدًا في كل مرة ستكون مشكلة إلى حد ما :)

المزيد من القراءة:

تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION