مرحبًا! محاضرة اليوم ستكون مقسمة إلى قسمين. سنكرر بعض المواضيع القديمة التي تطرقنا إليها من قبل، وننظر إلى بعض الميزات الجديدة :) لنبدأ بالموضوع الأول. التكرار هو أم التعلم :) لقد استخدمت بالفعل فئة مثل
BufferedReader
. أتمنى أنك لم تنسى هذا الأمر بعد:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
قبل مواصلة القراءة، حاول أن تتذكر ما System.in, InputStreamReader, BufferedReader
هو المسؤول عن كل مكون ( ) وما هو مطلوب منه. حدث؟ إذا لم يكن الأمر كذلك، فلا تقلق :) إذا كنت قد نسيت شيئًا ما في هذه المرحلة، فأعد قراءة هذه المحاضرة المخصصة للقراء مرة أخرى. دعونا نتذكر بإيجاز ما يمكن أن يفعله كل منهم. System.in
هو موضوع لتلقي البيانات من لوحة المفاتيح. من حيث المبدأ، لتنفيذ منطق قراءة النص، سيكون واحدا كافيا بالنسبة لنا. ولكن، كما تتذكر، System.in
يمكنه قراءة وحدات البايت فقط، وليس الأحرف:
public class Main {
public static void main(String[] args) throws IOException {
while (true) {
int x = System.in.read();
System.out.println(x);
}
}
}
إذا قمنا بتشغيل هذا الكود وأدخلنا الحرف "Y" في وحدة التحكم، فسيكون الناتج كما يلي:
Й
208
153
10
تشغل الأحرف السيريلية 2 بايت في الذاكرة، والتي يتم عرضها على الشاشة (والرقم 10 هو تمثيل البايت لفاصل الأسطر، أي الضغط على Enter). تعد قراءة البايتات أمرًا ممتعًا، لذا فإن استخدامها System.in
في شكلها النقي سيكون غير مريح. من أجل قراءة الحروف السيريلية (وليس فقط) المفهومة للجميع، نستخدمها 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);
}
}
}
إذا أدخلنا نفس الحرف "Y" في وحدة التحكم، ستكون النتيجة مختلفة هذه المرة:
Й
1049
10
InputStreamReader
تحويل بايتي القراءة (208، 153) إلى رقم واحد 1049. هذه هي القراءة بالأحرف. 1049 يتوافق مع حرف "Y" ويمكن التحقق منه بسهولة:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
إخراج وحدة التحكم:
Й
حسنًا، بالنسبة لـ BufferedReader
"a (وبشكل عام - BufferedAnything)، يتم استخدام الفئات المخزنة لتحسين الأداء. يعد الوصول إلى مصدر البيانات (ملف، وحدة تحكم، مورد على الإنترنت) عملية مكلفة إلى حد ما من حيث الأداء. لذلك، من أجل تقليل عدد هذه المكالمات، BufferedReader
يقوم بقراءة البيانات وتجميعها في مخزن مؤقت خاص، حيث يمكننا تلقيها لاحقًا. ونتيجة لذلك، يتم تقليل عدد المكالمات إلى مصدر البيانات عدة مرات أو حتى عشرات المرات! ميزة إضافية أخرى لـ BufferedReader
"a وميزته على العادي InputStreamReader
" هي الطريقة المفيدة للغاية 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("Пользователь ввел следующий текст:");
System.out.println(s);
reader.close();
}
}
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
Пользователь ввел следующий текст:
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
بالطبع، BufferedReader
إنها آلية مرنة للغاية وتتيح لك العمل ليس فقط مع لوحة المفاتيح. يمكنك قراءة البيانات، على سبيل المثال، مباشرة من الإنترنت بمجرد تمرير عنوان URL المطلوب إلى القارئ:
public class URLReader {
public static void main(String[] args) throws Exception {
URL oracle = new URL("https://www.oracle.com/index.html");
BufferedReader in = new BufferedReader(
new InputStreamReader(oracle.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
يمكنك قراءة البيانات من ملف عن طريق تمرير المسار إليه:
public class Main {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("testFile.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream));
String str;
while ((str = reader.readLine()) != null) {
System.out.println (str);
}
reader.close();
}
}
استبدال System.out
الآن دعونا نلقي نظرة على احتمال واحد مثير للاهتمام لم نتطرق إليه من قبل. كما تتذكر على الأرجح،System
يوجد حقلان ثابتان في الفصل - System.in
و System.out
. هؤلاء الأخوة التوأم هم كائنات من فئة الخيط. System.in
- فئة مجردة InputStream
. صف . System.out
_ PrintStream
الآن سوف نتحدث على وجه التحديد عن System.out
. إذا ذهبنا إلى الكود المصدري للفئة System
، فسنرى هذا:
public final class System {
……………...
public final static PrintStream out = null;
…………
}
لذلك، System.out
مجرد متغير فئة ثابتة عاديةSystem
. ليس هناك سحر فيه :) المتغير out
ينتمي إلى الفصل PrintStream
. إليك سؤال مثير للاهتمام: لماذا، عند تنفيذ التعليمات البرمجية، System.out.println()
يظهر الإخراج في وحدة التحكم وليس في مكان آخر؟ وهل من الممكن تغيير هذا بطريقة أو بأخرى؟ على سبيل المثال، نريد قراءة البيانات من وحدة التحكم وكتابتها في ملف نصي. هل من الممكن تنفيذ مثل هذا المنطق بطريقة أو بأخرى دون استخدام فئات إضافية للقارئ والكاتب، ولكن ببساطة باستخدام System.out
؟ ما زال ذلك ممكنًا :) وعلى الرغم من أن المتغير System.out
تم تعيينه بواسطة مُعدِّل final
، فلا يزال بإمكاننا القيام بذلك! إذن ماذا نحتاج لهذا؟ أولاً ، نحتاج إلى كائن فئة جديد PrintStream
بدلاً من الكائن الحالي. الكائن الحالي المثبت في الفصل System
لا يناسبنا بشكل افتراضي: فهو يشير إلى وحدة التحكم. نحن بحاجة إلى إنشاء ملف جديد يشير إلى ملف نصي باعتباره "الوجهة" لبياناتنا. ثانياً ، عليك أن تفهم كيفية تعيين قيمة جديدة للمتغير System.out
. لا يمكنك أن تفعل ذلك بهذه الطريقة، لأنه تم وضع علامة final
. لنبدأ من النهاية. يحتوي الفصل System
على الطريقة التي نحتاجها بالضبط - setOut()
. يأخذ كائنًا كمدخل PrintStream
ويحدده كنقطة إخراج. فقط ما نحتاجه! كل ما تبقى هو إنشاء الكائن PrintStream
. من السهل أيضًا القيام بذلك:
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
سيبدو الكود بأكمله كما يلي:
public class SystemRedirectService {
public static void main(String arr[]) throws FileNotFoundException
{
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
/*Сохраним текущее meaning System.out в отдельную переменную, чтобы потом
можно было переключиться обратно на вывод в консоль*/
PrintStream console = System.out;
// Присваиваем System.out новое meaning
System.setOut(filePrintStream);
System.out.println("Эта строка будет записана в текстовый файл");
// Возвращаем System.out старое meaning
System.setOut(console);
System.out.println("А эта строка - в консоль!");
}
}
ونتيجة لذلك، سيتم كتابة السطر الأول في ملف نصي، وسيتم إخراج الثاني إلى وحدة التحكم :) يمكنك نسخ هذا الرمز إلى IDE الخاص بك وتشغيله. من خلال فتح الملف النصي، سترى أن السطر المطلوب قد تم كتابته هناك بنجاح :) وبهذا تنتهي المحاضرة. تذكرنا اليوم كيفية العمل مع التدفقات والقراء، وتذكرنا مدى اختلافهم عن بعضهم البعض وتعرفنا على الميزات الجديدة System.out
التي استخدمناها في كل درس تقريبًا :) نراكم في المحاضرات القادمة!
GO TO FULL VERSION