CodeGym /مدونة جافا /Random-AR /تدرب على العمل مع فئتي BufferedReader وInputStreamReader
John Squirrels
مستوى
San Francisco

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

نشرت في المجموعة
أهلاً! سيتم تقسيم درس اليوم إلى قسمين للراحة. سنكرر بعض المواضيع القديمة التي تطرقنا إليها سابقًا، وسنأخذ في الاعتبار بعض الميزات الجديدة :) لنبدأ بالموضوع الأول. لقد قمت بالفعل بفصل دراسي مثل 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);
       }
   }
}
إذا قمنا بتنفيذ هذا الرمز وأدخلنا الحرف السيريلي "Й"، فسيكون الناتج:

Й
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);
       }
   }
}
ندخل نفس الحرف "Й"، لكن النتيجة مختلفة هذه المرة:

Й 
1049 
10
InputStreamReaderتحويل بايتين (208 و153) إلى الرقم الفردي 1049. هذا هو ما تعنيه قراءة الأحرف. 1049 يتوافق مع الحرف السيريلي "Й". يمكننا بسهولة إقناع أنفسنا بأن هذا صحيح:
public class Main {

   public static void main(String[] args) throws IOException {
       char x = 1049;
       System.out.println(x);
   }
}
إخراج وحدة التحكم:

Й
وكما forBufferedReader(وبشكل عام BufferedAnythingYouWant)، يتم استخدام الفئات المخزنة لتحسين الأداء. يعد الوصول إلى مصدر البيانات (ملف، وحدة تحكم، مورد ويب) مكلفًا للغاية من حيث الأداء. لذلك، من أجل تقليل عدد مرات الوصول، BufferedReaderنقوم بقراءة البيانات وتجميعها في مخزن مؤقت خاص، ونحصل عليها من هناك. ونتيجة لذلك، يتم تقليل عدد مرات الوصول إلى مصدر البيانات - ربما بعدة مراتب من حيث الحجم! إحدى BufferedReaderميزات s وميزته على العادي 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 ("The user entered the following text:");
       System.out.println(s);
       reader.close();
   }
}

BufferedReader+InputStreamReader is faster than InputStreamReader alone 
The user entered the following text: 
BufferedReader+InputStreamReader is faster than InputStreamReader alone
تدرب على العمل مع فئتي 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"));
       /* Save the current value of System.out in a separate variable so that later
       we can switch back to console output */

       PrintStream console = System.out;
       // Assign a new value to System.out
       System.setOut(filePrintStream);
       System.out.println("This line will be written to the text file");

       // Restore the old value of System.out
       System.setOut(console);
       System.out.println("But this line will be output to the console!");
   }
}
ونتيجة لذلك، تتم كتابة السلسلة الأولى في الملف النصي، ويتم عرض السلسلة الثانية في وحدة التحكم :) يمكنك نسخ هذا الرمز إلى IDE الخاص بك وتشغيله. افتح الملف النصي وسترى أن السلسلة قد تمت كتابتها هناك بنجاح :) وبهذا يكون درسنا قد وصل إلى النهاية. لقد تذكرنا اليوم كيفية العمل مع التدفقات والقراء. تذكرنا مدى اختلافها عن بعضها البعض وتعرفنا على بعض القدرات الجديدة System.outالتي استخدمناها في كل درس تقريبًا :) حتى الدروس التالية!

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

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