CodeGym /בלוג Java /Random-HE /תרגל עבודה עם השיעורים BufreredReader ו-InputStreamReader...
John Squirrels
רָמָה
San Francisco

תרגל עבודה עם השיעורים BufreredReader ו-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מהתכונות והיתרון שלה על פני הרגילות 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
תרגל עבודה עם השיעורים BufreredReader ו-InputStreamReader - 2כמובן, BufferedReaderהוא מאוד גמיש. אתה לא מוגבל לעבודה עם המקלדת. לדוגמה, אתה יכול לקרוא נתונים ישירות מהאינטרנט, פשוט על ידי העברת כתובת האתר הנדרשת לקורא:
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מסומן ב- finalmodifier!  תרגל עבודה עם השיעורים BufreredReader ו-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