JavaRush /مدونة جافا /Random-AR /تدرب على العمل مع فئتي BufferedReader وInputStreamReader

تدرب على العمل مع فئتي BufferedReader وInputStreamReader

نشرت في المجموعة
مرحبًا! محاضرة اليوم ستكون مقسمة إلى قسمين. سنكرر بعض المواضيع القديمة التي تطرقنا إليها من قبل، وننظر إلى بعض الميزات الجديدة :) تدرب على العمل مع فئتي BufferedReader وInputStreamReader - 1لنبدأ بالموضوع الأول. التكرار هو أم التعلم :) لقد استخدمت بالفعل فئة مثل 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 وInputStreamReader - 2بالطبع، 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، فلا يزال بإمكاننا القيام بذلك! تدرب على العمل مع فئتي BufferedReader وInputStreamReader - 3إذن ماذا نحتاج لهذا؟ أولاً ، نحتاج إلى كائن فئة جديد 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التي استخدمناها في كل درس تقريبًا :) نراكم في المحاضرات القادمة!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION