CodeGym /בלוג Java /Random-HE /קלט/פלט ב-Java. מחלקות FileInputStream, FileOutputStream ...
John Squirrels
רָמָה
San Francisco

קלט/פלט ב-Java. מחלקות FileInputStream, FileOutputStream ו- BufferedInputStream

פורסם בקבוצה
"היי! בשיעור של היום, נמשיך בשיחתנו על זרמי קלט ופלט ב-Java ( Java I/O ). זה לא השיעור הראשון בנושא זה, ובוודאי לא יהיה האחרון :) קלט/פלט ב-Java.  מחלקות FileInputStream, FileOutputStream ו- BufferedInputStream - 1שכן קורה, שפת Java מספקת דרכים רבות לעבוד עם I/O. יש לא מעט מחלקות שמיישמות את הפונקציונליות הזו, אז חילקנו אותן למספר שיעורים - כדי שלא תתבלבלו מההתחלה :) בעבר נגענו בשיעורים BufferedReader, כמו גם בכיתות InputStreamהמופשטות OutputStreamובכמה צאצאים. היום נשקול 3 כיתות חדשות: FileInputStream,  FileOutputStream, ו  BufferedInputStream.

המחלקה FileOutputStream

המטרה העיקרית של FileOutputStreamהמחלקה היא לכתוב בייטים לקובץ. שום דבר מסובך :) FileOutputStreamהוא אחד המימושים של OutputStreamהמחלקה המופשטת. בבנאי, אובייקטים של מחלקה זו לוקחים את הנתיב לקובץ היעד (שם יש לכתוב את הבתים) או אובייקט File. נבחן דוגמאות של כל אחד מהם:
public class Main {

   public static void main(String[] args) throws IOException {

       File file = new File("C:\\Users\\Username\\Desktop\\test.txt");
       FileOutputStream fileOutputStream = new FileOutputStream(file);

       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!";

       fileOutputStream.write(greetings.getBytes());
       fileOutputStream.close();
   }
}
בעת יצירת Fileהאובייקט העברנו את הנתיב הרצוי לבנאי. אנחנו לא צריכים ליצור אותו מראש: אם הוא לא קיים, התוכנית תיצור אותו. אתה יכול גם להסתדר בלי ליצור אובייקט נוסף, פשוט להעביר מחרוזת עם הנתיב:
public class Main {

    public static void main(String[] args) throws IOException {

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt");
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!";

       fileOutputStream.write(greetings.getBytes());
       fileOutputStream.close();
   }
}
התוצאה בשני המקרים תהיה זהה. אנחנו יכולים לפתוח את הקובץ שלנו ולראות שם את הדברים הבאים:

Hi! Welcome to CodeGym — The best site for would-be programmers!
אבל יש כאן ניואנס אחד. נסה להריץ את הקוד מהדוגמה למעלה מספר פעמים ברציפות. לאחר מכן עיין בקובץ וענה על השאלה הזו: כמה שורות יש לו? רק אחד. אבל הרצת את הקוד כמה פעמים. מסתבר שהנתונים מוחלפים בכל פעם - הישן מוחלף בחדש. מה עושים אם זה לא מתאים לנו ואנחנו צריכים לכתוב ברצף לקובץ? מה אם נרצה לכתוב את הברכה שלנו לקובץ שלוש פעמים ברציפות? הכל מאוד פשוט. מכיוון שהשפה לא יכולה לדעת איזו התנהגות אנחנו צריכים בכל מקרה, המעצב FileOutputStreamיכול לקחת פרמטר נוסף - boolean append. אם הערך שלו נכון, הנתונים ייכתבו לסוף הקובץ. אם הוא שקר (וברירת המחדל הוא שקר), כל נתונים ישנים יימחקו ויוחלף בנתונים חדשים. בוא נבדוק זאת על ידי הפעלת הקוד ששונה שלוש פעמים:
public class Main {

   public static void main(String[] args) throws IOException {

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true);
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!\r\n";

       fileOutputStream.write(greetings.getBytes());
       fileOutputStream.close();
   }
}
תוכן הקובץ:

Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers!
עכשיו זה אחרת! אל תשכח את התכונה הזו בעת שימוש בשיעורי I/O. הייתה תקופה שבה ביליתי שעות במשימות, ביליתי שעות במוח, בניסיון להבין איך הנתונים שלי נעלמים מקבצים :) וכמובן, בדיוק כמו בשיעורי I/O אחרים, אל תשכחו להשתמש close()בשיטה לפנות משאבים.

המחלקה FileInputStream

למטרה FileInputStreamההפוכה - קריאת בתים מקובץ. בדיוק כמו FileOutputStreamיורשת OutputStream, מחלקה זו נובעת מהמחלקה InputStreamהמופשטת. נכתוב כמה שורות טקסט בקובץ " test.txt " שלנו:

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
קלט/פלט ב-Java.  מחלקות FileInputStream, FileOutputStream ו- BufferedInputStream - 2הנה איך זה נראה לקרוא נתונים מקובץ באמצעות FileInputStream:
public class Main {

   public static void main(String[] args) throws IOException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");

       int i;

       while((i=fileInputStream.read())!= -1){

           System.out.print((char)i);

       }
   }
}
אנו קוראים בית אחד מהקובץ, ממירים את הבייטים הנקראים לתווים ומציגים אותם בקונסולה. והנה פלט הקונסולה:

So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters

המחלקה BufferedInputStream

אני חושב, בהתחשב בידע משיעורי העבר, אתה יכול להגיד בקלות למה אנחנו צריכים את השיעור BufferedInputStreamואיזה יתרונות יש לו בהשוואה FileInputStream:) כבר נתקלנו בזרמים מאוחסנים, אז נסו לנחש (או לזכור) לפני שאתם ממשיכים לקרוא :) נחוצים זרמים ממוגנים בעיקר כדי לייעל את ה-I/O. גישה למקור נתונים, כמו קריאה מקובץ, היא פעולה יקרה מבחינת ביצועים ולגשת לקובץ כדי לקרוא כל בייט זה בזבוז. זו הסיבה BufferedInputStreamשקורא נתונים לא בייט אחד בכל פעם, אלא בבלוקים, ומאחסן אותם באופן זמני במאגר מיוחד. זה מאפשר לנו לייעל את התוכנית על ידי הפחתת מספר הפעמים שאנו ניגשים לקובץ. בוא נראה איך זה נראה:
public class Main {

   public static void main(String[] args) throws IOException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200);

       int i;

       while((i = bufferedInputStream.read())!= -1){

           System.out.print((char)i);
       }
   }
}
כאן יצרנו אובייקט BufferedInputStream. הבנאי שלו לוקח מופע של InputStreamהמחלקה או כל אחד מהצאצאים שלה, כך גם FileInputStreamיעשה. כארגומנט נוסף, הוא לוקח את גודל המאגר בבתים. הודות לטיעון זה, הנתונים ייקראו כעת מהקובץ לא בייט אחד בכל פעם, אלא 200 בייט בכל פעם! תארו לעצמכם כמה צמצמנו את מספר הגישה לקבצים. כדי להשוות ביצועים, אתה יכול לקחת קובץ טקסט גדול (מספר מגה בייט של טקסט) ולהשוות את משך הזמן שלוקח באלפיות שניות לקרוא ולפלט לקונסולה באמצעות FileInputStreamו BufferedInputStream. הנה קוד שמדגים את שתי האפשרויות:
public class Main {

   public static void main(String[] args) throws IOException {

       Date date = new Date();

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf");
       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

       int i;
       while((i = bufferedInputStream.read())!= -1){

           System.out.print((char)i);
       }

       Date date1 = new Date();
       System.out.println((date1.getTime() - date.getTime()));
   }
}


public class Main {

   public static void main(String[] args) throws IOException {

       Date date = new Date();
       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf");

       int i;
       while((i = fileInputStream.read())!= -1){

           System.out.print((char)i);
       }


       Date date1 = new Date();
       System.out.println((date1.getTime() - date.getTime()));
   }
}
כשקראתי קובץ של 1.5 מגה-בייט במחשב שלי, FileInputStreamהשלמתי את העבודה תוך ~3500 מילישניות, אבל BufferedInputStreamהצלחתי אותה תוך ~1700 מילישניות. כפי שאתה יכול לראות, הזרם המאוחסן ייעל את העבודה, חתך אותה לשניים! :) נמשיך ללמוד שיעורי I/O - נתראה בקרוב!
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION