"Hai! Dalam pelajaran hari ini, kita akan meneruskan perbualan kita tentang aliran input dan output dalam Java ( Java I/O
). Ini bukan pelajaran pertama mengenai topik ini, dan pastinya ia bukan yang terakhir :) berlaku, bahasa Java menyediakan banyak cara untuk bekerja dengan I/O. Terdapat beberapa kelas yang melaksanakan fungsi ini, jadi kami telah membahagikannya kepada beberapa pelajaran — supaya anda tidak akan keliru dari awal :) pelajaran, kami menyentuh tentang
Inilah rupanya untuk membaca data daripada fail menggunakan

BufferedReader
, serta kelas InputStream
dan OutputStream
abstrak dan beberapa keturunan. Hari ini kami akan mempertimbangkan 3 kelas baharu: FileInputStream
, FileOutputStream
, dan BufferedInputStream
.
Kelas FileOutputStream
Tujuan utama kelasFileOutputStream
adalah untuk menulis bait ke fail. Tiada yang rumit :) FileOutputStream
adalah salah satu pelaksanaan kelas OutputStream
abstrak. Dalam pembina, objek kelas ini mengambil sama ada laluan ke fail sasaran (di mana bait harus ditulis) atau objek File
. Kami akan mengkaji contoh setiap:
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();
}
}
Apabila mencipta File
objek, kami melepasi laluan yang dikehendaki kepada pembina. Kami tidak perlu menciptanya terlebih dahulu: jika ia tidak wujud, program akan menciptanya. Anda juga boleh bertahan tanpa membuat objek tambahan, hanya menghantar rentetan dengan laluan:
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();
}
}
Keputusan dalam kedua-dua kes adalah sama. Kami boleh membuka fail kami dan melihat perkara berikut di sana:
Hi! Welcome to CodeGym — The best site for would-be programmers!
Tetapi ada satu nuansa di sini. Cuba jalankan kod daripada contoh di atas beberapa kali berturut-turut. Kemudian lihat dalam fail dan jawab soalan ini: berapa banyak baris yang ada? Hanya satu. Tetapi anda menjalankan kod itu beberapa kali. Ternyata data ditimpa setiap kali — yang lama digantikan dengan yang baru. Apa yang kita lakukan jika itu tidak sesuai dengan kita dan kita perlu menulis secara berurutan ke fail? Bagaimana jika kita ingin menulis ucapan kita pada fail tiga kali berturut-turut? Semuanya sangat mudah. Oleh kerana bahasa tidak dapat mengetahui tingkah laku yang kita perlukan dalam setiap kes, contrucutor FileOutputStream
boleh mengambil parameter tambahan —boolean append
. Jika nilainya benar, data akan ditulis ke penghujung fail. Jika ia palsu (dan secara lalai ia palsu), sebarang data lama akan dipadamkan dan digantikan dengan data baharu. Mari semak ini dengan menjalankan kod yang diubah suai kami tiga kali:
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();
}
}
Kandungan fail:
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!
Sekarang itu berbeza! Jangan lupa tentang ciri ini apabila menggunakan kelas I/O. Ada masanya saya menghabiskan masa berjam-jam untuk tugasan, memerah otak selama berjam-jam, cuba memahami bagaimana data saya hilang daripada fail :) Dan sudah tentu, sama seperti kelas I/O yang lain, jangan lupa gunakan kaedah close()
tersebut kepada sumber percuma.
Kelas FileInputStream
TheFileInputStream
mempunyai tujuan yang bertentangan — membaca bait daripada fail. Sama seperti FileOutputStream
inherits OutputStream
, kelas ini berasal daripada InputStream
kelas abstrak. Kami akan menulis beberapa baris teks dalam fail " test.txt " kami:
"So close no matter how far
Couldn't be much more from the heart
Forever trusting who we are
And nothing else matters"

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);
}
}
}
Kami membaca satu bait daripada fail, menukar bait baca kepada aksara dan memaparkannya pada konsol. Dan inilah output konsol:
So close no matter how far
Couldn't be much more from the heart
Forever trusting who we are
And nothing else matters
Kelas BufferedInputStream
Saya fikir, berdasarkan pengetahuan dari pelajaran lepas, anda boleh dengan mudah mengatakan mengapa kami memerlukan kelasBufferedInputStream
dan apakah kelebihannya berbanding dengan FileInputStream
:) Kami telah pun menemui aliran buffer, jadi cuba teka (atau ingat) sebelum anda meneruskan bacaan :) Strim buffer diperlukan terutamanya untuk mengoptimumkan I/O. Mengakses sumber data, seperti membaca daripada fail, adalah operasi yang mahal dari segi prestasi Dan untuk mengakses fail untuk membaca setiap bait adalah membazir. Itulah sebabnya BufferedInputStream
membaca data bukan satu bait pada satu masa, tetapi dalam blok, dan menyimpannya buat sementara waktu dalam penimbal khas. Ini membolehkan kami mengoptimumkan program dengan mengurangkan bilangan kali kami mengakses fail. Mari lihat bagaimana ini kelihatan:
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);
}
}
}
Di sini kami mencipta BufferedInputStream
objek. Pembinanya mengambil contoh kelas InputStream
atau mana-mana keturunannya, begitu FileInputStream
juga. Sebagai hujah tambahan, ia mengambil saiz penimbal dalam bait. Terima kasih kepada hujah ini, data kini akan dibaca daripada fail bukan satu bait pada satu masa, tetapi 200 bait pada satu masa! Bayangkan betapa kami telah mengurangkan bilangan akses fail. Untuk membandingkan prestasi, anda boleh mengambil fail teks yang besar (beberapa megabait teks) dan membandingkan tempoh masa yang diperlukan dalam milisaat untuk membaca dan mengeluarkan ke konsol menggunakan FileInputStream
dan BufferedInputStream
. Berikut ialah kod yang menunjukkan kedua-dua pilihan:
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()));
}
}
Apabila membaca fail 1.5 MB pada komputer saya, FileInputStream
selesaikan kerja dalam ~3500 milisaat, tetapi BufferedInputStream
menguruskannya dalam ~1700 milisaat. Seperti yang anda lihat, aliran penimbal mengoptimumkan kerja, memotongnya separuh! :) Kami akan terus belajar kelas I/O — jumpa lagi!
GO TO FULL VERSION