מדריך ל- BufferedReader

1. סקירה כללית

BufferedReader הוא מחלקה המפשטת קריאת טקסט מזרם קלט תווים. הוא מאגר את התווים על מנת לאפשר קריאה יעילה של נתוני טקסט.

במדריך זה, נבחן כיצד להשתמש ב- BufferedReader מעמד.

2. מתי להשתמש BufferedReader

בכללי, BufferedReader שימושי אם אנו רוצים לקרוא טקסט מכל סוג של מקור קלט, בין אם זה קבצים, שקעים או משהו אחר.

פשוט שים, זה מאפשר לנו למזער את מספר פעולות הקלט / פלט על ידי קריאת נתחי תווים ושמירתם במאגר פנימי. בעוד שבמאגר יש נתונים, הקורא יקרא ממנו במקום ישירות מהזרם הבסיסי.

2.1. חציץ קורא אחר

כמו רוב שיעורי ה- I / O של Java,BufferedReader מכשירים דפוס מעצב, כלומר הוא מצפה א קוֹרֵא בבנאי שלה. באופן זה הוא מאפשר לנו להאריך בצורה גמישה מופע של a קוֹרֵא יישום עם פונקציונליות חציצה:

BufferedReader reader = BufferedReader חדש (FileReader חדש ("src / main / resources / input.txt"));

אבל אם חציצה לא משנה לנו היינו יכולים פשוט להשתמש ב- FileReader באופן ישיר:

קורא FileReader = FileReader חדש ("src / main / resources / input.txt");

בנוסף למאגר, BufferedReader מספק גם כמה פונקציות עוזרות נחמדות לקריאת קבצים שורה אחר שורה. לכן, למרות שזה עשוי להיראות פשוט יותר לשימוש FileReader באופן ישיר, BufferedReader יכול להיות עזרה גדולה.

2.2. חציצה זרם

בכללי, אנחנו יכולים להגדיר BufferedReader לקחת כל סוג של זרם קלטכמקור בסיסי. אנחנו יכולים לעשות את זה באמצעות InputStreamReader ועוטף אותו בבנאי:

BufferedReader reader = BufferedReader חדש (InputStreamReader חדש (System.in));

בדוגמה שלעיל אנו קוראים מתוך System.in המתאים בדרך כלל לקלט מהמקלדת. באופן דומה, נוכל להעביר זרם קלט לקריאה משקע, קובץ או כל סוג קלט טקסטואלי שניתן להעלות על הדעת. התנאי היחיד הוא שיש מתאים InputStream יישום עבור זה.

2.3. BufferedReader לעומת סורק

כחלופה, נוכל להשתמש ב- סוֹרֵק בכיתה כדי להשיג את אותה פונקציונליות כמו עם BufferedReader.

עם זאת, ישנם הבדלים משמעותיים בין שני המחלקות הללו אשר יכולים להפוך אותם לנוחים יותר או פחות עבורנו, בהתאם למקרה השימוש שלנו:

  • BufferedReader מסונכרן (בטיחות תבריג) ואילו הסורק אינו
  • סוֹרֵק יכול לנתח סוגים וחוטים פרימיטיביים באמצעות ביטויים רגולריים
  • BufferedReader מאפשר לשנות את גודל המאגר בעוד לסורק יש גודל מאגר קבוע
  • BufferedReader בעל גודל חיץ ברירת מחדל גדול יותר
  • סוֹרֵק מסתיר IOException, בזמן BufferedReader מכריח אותנו להתמודד עם זה
  • BufferedReader הוא בדרך כלל מהיר יותר מ סוֹרֵק כי זה קורא רק את הנתונים מבלי לנתח אותם

עם זאת בראש, אם אנו מנתחים אסימונים בודדים בקובץ, אז סוֹרֵק ירגיש קצת יותר טבעי מ BufferedReader. אבל, פשוט לקרוא שורה בכל פעם זה המקום BufferedReader זורחת.

אם יש צורך, יש לנו גם מדריך בנושא סוֹרֵק גם כן.

3. קריאת טקסט עם BufferedReader

בואו נעבור את כל התהליך של בנייה, שימוש והרס של a BufferReader כראוי לקריאה מקובץ טקסט.

3.1. אתחול א BufferedReader

קוֹדֶם כֹּל, בואו ניצור BufferedReader באמצעות שלה BufferedReader (קורא) בַּנַאִי:

BufferedReader reader = BufferedReader חדש (FileReader חדש ("src / main / resources / input.txt"));

עוטף את FileReader כמו זו דרך נחמדה להוסיף חציצה כהיבט לקוראים אחרים.

כברירת מחדל, זה ישתמש במאגר של 8 KB. עם זאת, אם אנו רוצים לחסום בלוקים קטנים יותר או גדולים יותר, נוכל להשתמש ב- BufferedReader (Reader, int) בַּנַאִי:

BufferedReader reader = BufferedReader חדש (FileReader חדש ("src / main / resources / input.txt")), 16384);

פעולה זו תקבע את גודל המאגר ל- 16384 בתים (16 KB).

גודל המאגר האופטימלי תלוי בגורמים כמו סוג זרם הקלט והחומרה שעליה פועל הקוד. מסיבה זו, כדי להשיג את גודל המאגר האידיאלי, עלינו למצוא אותו בעצמנו באמצעות ניסויים.

עדיף להשתמש בכוחות של 2 כגודל חיץ מכיוון שלרוב התקני החומרה יש כוח של 2 כגודל הבלוק.

סוף כל סוף, יש עוד דרך שימושית ליצור BufferedReader משתמש ב קבצים מעמד עוזר מ ה java.nioממשק API:

BufferedReader reader = Files.newBufferedReader (Paths.get ("src / main / resources / input.txt"))

יוצר אותוככה זו דרך נחמדה לחוצץ אם אנחנו רוצים לקרוא קובץ כי אנחנו לא צריכים ליצור ידנית קובץ FileReader קודם ואז עוטפים אותו.

3.2. קריאת שורה אחר שורה

לאחר מכן, בואו לקרוא את תוכן הקובץ באמצעות ה- קריאת שורה שיטה:

מחרוזת readAllLines (קורא BufferedReader) זורק IOException {StringBuilder content = new StringBuilder (); קו מיתרים; בעוד ((שורה = reader.readLine ())! = null) {content.append (שורה); content.append (System.lineSeparator ()); } להחזיר content.toString (); }

אנחנו יכולים לעשות את אותו הדבר כמו לעיל באמצעות ה- שורות שיטה שהוצגה ב- Java 8 קצת יותר פשוט:

מחרוזת ציבורית readAllLinesWithStream (קורא BufferedReader) {return reader.lines () .collect (Collectors.joining (System.lineSeparator ())); }

3.3. סגירת הזרם

לאחר השימוש ב- BufferedReaderאנחנו חייבים לקרוא לזה סגור() שיטה לשחרור כל משאבי מערכת הקשורים אליו. זה נעשה באופן אוטומטי אם אנו משתמשים ב- נסה עם משאבים לַחסוֹם:

נסה (BufferedReader reader = new BufferedReader (FileReader new ("src / main / resources / input.txt"))) {return readAllLines (reader); }

4. שיטות שימושיות אחרות

כעת נתמקד בשיטות שימושיות שונות הקיימות ב- BufferedReader.

4.1. קריאת דמות יחידה

אנחנו יכולים להשתמש ב- לקרוא() שיטה לקרוא דמות אחת. בואו לקרוא את כל התוכן תו אחר דמות עד סוף הזרם:

מחרוזת ציבורית readAllCharsOneByOne (קורא BufferedReader) זורק IOException {StringBuilder content = new StringBuilder (); ערך int; בעוד ((value = reader.read ())! = -1) {content.append ((char) value); } להחזיר content.toString (); }

זה יקרא את התווים (שהוחזרו כערכי ASCII), וישליך אותם ל לְהַשְׁחִיר ולצרף אותם לתוצאה. אנו חוזרים על כך עד סוף הזרם, המצוין על ידי ערך התגובה -1 מה- לקרוא() שיטה.

4.2. קריאת תווים מרובים

אם אנו רוצים לקרוא מספר תווים בו זמנית, נוכל להשתמש בשיטה קרא (char [] cbuf, int off, int len):

מחרוזת ציבורית readMultipleChars (קורא BufferedReader) זורק IOException {int אורך; char [] chars = char char [length]; int charsRead = reader.read (תווים, 0, אורך); תוצאת מחרוזת; אם (charsRead! = -1) {result = מחרוזת חדשה (chars, 0, charsRead); } אחר {result = ""; } להחזיר תוצאה; }

בדוגמת הקוד שלעיל נקרא עד 5 תווים במערך char ונבנה ממנו מחרוזת. במקרה שלא נקראו תווים בניסיון הקריאה שלנו (כלומר הגענו לסוף הזרם), פשוט נחזיר מחרוזת ריקה.

4.3. דילוג על דמויות

אנו יכולים גם לדלג על מספר תווים נתון על ידי קריאה ל דלג (ארוך n) שיטה:

@Test הציבור בטל givenBufferedReader_whensSkipChars_thenOk () זורק IOException {StringBuilder תוצאה = StringBuilder חדש (); נסה (BufferedReader reader = new BufferedReader (StringReader new ("1__2__3__4__5"))) {int; בעוד ((value = reader.read ())! = -1) {result.append ((char) value); reader.skip (2L); }} assertEquals ("12345", תוצאה); }

בדוגמה שלעיל אנו קוראים ממחרוזת קלט המכילה מספרים המופרדים על ידי שני קו תחתון. על מנת לבנות מחרוזת המכילה רק את המספרים, אנו מדלגים על קו התחתון על ידי קריאת ה- לדלג שיטה.

4.4. סימן ו אִתחוּל

אנחנו יכולים להשתמש ב- סימן (int readAheadLimit) ו אִתחוּל() שיטות לסמן מיקום כלשהו בזרם ולחזור אליו מאוחר יותר. כדוגמה קצת מהוגה, בואו נשתמש סימן() ו אִתחוּל() להתעלם מכל המרחבים הלבנים בתחילת זרם:

@Test הציבור בטל givenBufferedReader_whenSkipsWhitespacesAtBeginning_thenOk () זורק IOException {תוצאה מחרוזת; נסה (קורא BufferedReader = BufferedReader חדש (StringReader חדש ("Lorem ipsum dolor sit amet."))) {do {reader.mark (1); } בעוד (Character.isWhitespace (reader.read ())) reader.reset (); תוצאה = reader.readLine (); } assertEquals ("Lorem ipsum dolor sit amet.", תוצאה); }

בדוגמה שלעיל אנו משתמשים ב- סימן() שיטה לסימון המיקום שזה עתה קראנו. מתן ערך 1 פירושו שרק הקוד יזכור את הסימן לדמות אחת קדימה. זה שימושי כאן מכיוון שברגע שנראה את הדמות הראשונה שלנו שאיננה שטח לבן, נוכל לחזור ולקרוא מחדש את הדמות הזו מבלי שנצטרך לעבד מחדש את כל הזרם. בלי שיהיה לנו סימן, נאבד את ל במחרוזת הסופית שלנו.

שים לב כי בגלל סימן() יכול לזרוק לא נתמךOperationException, זה די מקובל לשייך markSupported () עם קוד שמפעיל סימן(). אף על פי כן, איננו זקוקים לכך כאן. זה בגלל markSupported () תמיד מחזיר נכון עבור BufferedReader.

כמובן, אולי נוכל לעשות את האמור לעיל קצת יותר באלגנטיות בדרכים אחרות, ואכן סימן ו אִתחוּל אינן שיטות אופייניות במיוחד. הם בהחלט מועילים, כאשר יש צורך להסתכל קדימה.

5. מסקנה

במדריך מהיר זה, למדנו כיצד לקרוא זרמי קלט תווים לדוגמא מעשית באמצעות BufferedReader.

לבסוף, קוד המקור של הדוגמאות זמין ב- Github.


$config[zx-auto] not found$config[zx-overlay] not found