CodeGym /จาวาบล็อก /สุ่ม /อินพุต/เอาต์พุตในภาษาจาวา คลาส FileInputStream, FileOutpu...
John Squirrels
ระดับ
San Francisco

อินพุต/เอาต์พุตในภาษาจาวา คลาส FileInputStream, FileOutputStream และ BufferedInputStream

เผยแพร่ในกลุ่ม
"สวัสดี! ในบทเรียนวันนี้ เราจะสนทนากันต่อเกี่ยวกับสตรีมอินพุตและเอาต์พุตใน Java ( Java I/O ) นี่ไม่ใช่บทเรียนแรกในหัวข้อนี้ และจะไม่ใช่บทเรียนสุดท้ายอย่างแน่นอน อินพุต/เอาต์พุตในภาษาจาวา  คลาส 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!
แต่มีความแตกต่างกันเล็กน้อยที่นี่ ลองเรียกใช้โค้ดจากตัวอย่างด้านบนหลายๆ ครั้งติดต่อกัน จากนั้นดูในไฟล์และตอบคำถามนี้: มีกี่บรรทัด แค่หนึ่ง. แต่คุณรันโค้ดหลายครั้ง ปรากฎว่าข้อมูลถูกเขียนทับทุกครั้ง ข้อมูลเก่าจะถูกแทนที่ด้วยข้อมูลใหม่ เราจะทำอย่างไรถ้าไม่เหมาะกับเราและเราต้องเขียนไฟล์ตามลำดับ? ถ้าเราต้องการเขียนคำทักทายลงในไฟล์ 3 ครั้งติดต่อกันล่ะ? ทุกอย่างง่ายมาก เนื่องจากภาษาไม่สามารถรู้ได้ว่าเราต้องการพฤติกรรมใดในแต่ละกรณี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

The 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"
อินพุต/เอาต์พุตในภาษาจาวา  คลาส 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 MB บนคอมพิวเตอร์ของฉันFileInputStreamทำงานเสร็จใน ~3500 มิลลิวินาที แต่BufferedInputStreamจัดการได้ใน ~1700 มิลลิวินาที อย่างที่คุณเห็น สตรีมที่บัฟเฟอร์ได้เพิ่มประสิทธิภาพการทำงาน โดยลดไปครึ่งหนึ่ง! :) เราจะเรียนคลาส I/O กันต่อ — แล้วพบกันใหม่!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION