Kata pengantar
Dalam artikel sebelumnya, kami memperkenalkan konten yang relevan dalam kerangka kerja streaming byte file Java, sementara artikel kami akan fokus pada konten yang relevan dari streaming karakter file.
Pertama -tama, harus jelas bahwa file pemrosesan aliran byte didasarkan pada byte, sementara file pemrosesan aliran karakter didasarkan pada karakter sebagai unit dasar.
Namun pada kenyataannya, esensi dari operasi aliran karakter adalah enkapsulasi dari dua proses "operasi aliran byte" + "pengkodean". Menurutmu begitu? Apakah Anda menulis karakter ke file, Anda perlu menyandikan karakter ke dalam biner, dan kemudian menulisnya ke file dalam byte sebagai unit dasar, atau Anda membaca karakter ke memori, Anda perlu membacanya dalam byte sebagai unit dasar dan kemudian mentranskodenya menjadi karakter.
Penting untuk memahami hal ini, yang akan menentukan pemahaman Anda secara keseluruhan tentang aliran karakter. Mari kita lihat desain API terkait bersama.
Pembaca/Penulis Kelas Dasar
Sebelum mempelajari Kelas Dasar Stream Karakter, kita perlu tahu bagaimana karakter diwakili dalam Java.
Pertama-tama, pengkodean karakter default di Java adalah: UTF-8, dan kita tahu bahwa karakter yang dikodekan UTF-8 disimpan menggunakan 1 hingga 4 byte, dan karakter yang lebih umum digunakan, semakin sedikit byte yang digunakan.
Jenis char didefinisikan sebagai dua ukuran byte, yaitu, untuk karakter biasa, sebuah char dapat menyimpan karakter, tetapi untuk beberapa set karakter komplementer, dua karakter sering digunakan untuk mewakili karakter.
Pembaca adalah kelas dasar untuk membaca aliran karakter, dan menyediakan operasi membaca karakter paling dasar. Mari kita lihat bersama.
Mari kita lihat konstruktornya terlebih dahulu:
Lock Object Lock; Protected Reader () {this.lock = this;} Protected Reader (Object Lock) {if (lock == null) {lempar nullPointerException baru (); } this.lock = lock;}Pembaca adalah kelas abstrak, sehingga tidak ada keraguan bahwa konstruktor ini dipanggil ke subkelas dan digunakan untuk menginisialisasi objek kunci kunci, yang akan kami jelaskan secara rinci nanti.
Public int read () melempar ioException {char cb [] = char baru [1]; if (baca (cb, 0, 1) == -1) return -1; lain return cb [0];} public int read (char cbuf []) melempar ioException {return read (cbuf, 0, cbuf.length);} abstrak int read public int (char cbuf [], int, int len)Operasi membaca karakter dasar ada di sini. Metode pertama digunakan untuk membaca karakter. Jika telah dibaca ke akhir file, itu akan mengembalikan -1. Hal yang sama diterima dengan int sebagai tipe nilai pengembalian, mengapa tidak menggunakan char? Alasannya sama, semua karena ketidakpastian interpretasi nilai -1.
Metode kedua mirip dengan metode ketiga, membaca karakter dari panjang yang ditentukan dari file dan menempatkannya ke dalam array target. Metode ketiga adalah metode abstrak, yang perlu diimplementasikan oleh subkelas, sedangkan metode kedua didasarkan padanya.
Ada beberapa metode lain yang serupa:
Metode-metode ini sebenarnya terkenal dan umumnya mirip dengan inputstream kami, dan mereka tidak memiliki implementasi inti. Saya tidak akan membahas detailnya di sini, Anda dapat secara kasar tahu apa yang ada di dalamnya.
Penulis adalah aliran karakter tertulis, yang digunakan untuk menulis satu atau lebih karakter ke dalam file. Tentu saja, metode penulisan spesifik masih merupakan metode abstrak dan harus diimplementasikan oleh subkelas, jadi kami tidak akan mengulanginya di sini.
Adaptor InPustStramReader/OutputStreamWriter
Aliran karakter adaptor mewarisi dari pembaca atau penulis kelas dasar, yang merupakan anggota yang sangat penting dari sistem aliran karakter. Fungsi utama adalah untuk mengubah aliran byte menjadi aliran karakter. Pertama -tama mari kita ambil adaptor baca sebagai contoh.
Pertama -tama, anggota intinya:
Private Final StreamDecoder SD;
StreamDecoder adalah dekoder yang digunakan untuk mengubah berbagai operasi byte menjadi operasi karakter yang sesuai. Kami akan menyebutkannya terus menerus dalam pengantar berikutnya, dan kami tidak akan menjelaskannya secara seragam di sini.
Lalu ada konstruktor:
inputStreamReader publik (inputStream in) {super (IN); coba {sd = streamDecoder.forInputStreamReader (di, this, (string) null); } catch (UnsupportedencodingException e) {lempar kesalahan baru (e); }} public inputStreamReader (inputStream in, string charsetName) melempar UnsupportedencodingException {super (IN); if (charsetname == null) lempar nullpointerException baru ("charsetname"); sd = streamDecoder.forInputStreamReader (dalam, ini, charsetname);}Tujuan dari dua konstruktor ini adalah untuk menginisialisasi dekoder ini. Metode ForinputStreamReader dipanggil, tetapi parameternya berbeda. Mari kita lihat implementasi metode ini:
Ini adalah pola pabrik statis yang khas. Tidak ada yang bisa dikatakan tentang tiga parameter, VAR0 dan VAR1, masing -masing mewakili instance aliran byte dan instance adaptor.
Parameter VAR2 sebenarnya mewakili nama pengkodean karakter. Jika nol, pengkodean karakter default sistem akan digunakan: UTF-8.
Akhirnya kita bisa mendapatkan instance dari decoder.
Hampir semua metode yang diperkenalkan selanjutnya diimplementasikan dengan mengandalkan dekoder ini.
Public String getEncoding () {return sd.getEncoding ();} public int read () melempar ioException {return sd.read ();} public int read (char cbuf [], int offset, int length) {return sd.read (cbuf, offset, length);} public void close () loss () {loss clows (cbuf, length, length);} public void close () loss () loss (cbuf, length);} public void close public close () public close () {) loss (cbuf, length);} public void close () public close () lamp close public;Kode implementasi metode terkait dalam dekoder masih relatif kompleks. Kami tidak akan melakukan penelitian mendalam di sini, tetapi ide implementasi umum adalah: proses "pembacaan aliran byte + decoding".
Tentu saja, harus ada instance streamencoder yang berlawanan di OutputStreamWriter untuk pengkodean karakter.
Terlepas dari ini, sisa operasi tidak berbeda, baik ditulis ke file melalui array karakter, ditulis ke file melalui string, atau ditulis ke file melalui 16 bit int int.
File Stream Filereader/Writer File
Aliran karakter file dapat dikatakan sangat sederhana. Tidak ada metode lain kecuali konstruktor, dan itu sepenuhnya tergantung pada aliran byte file.
Mari kita ambil filereader sebagai contoh.
Filereader mewarisi dari InputStreamReader, dan hanya memiliki tiga konstruktor berikut: FileReader publik (string fileName) melempar FileNoTFoundException {super new fileInputStream (fileName));} publicereader (File File) FileNoDeadSception {super baru fileIinprip (File) {file) (file) (file) (file) (file) {file); super (FileInputStream baru (FD));}Secara teori, semua aliran karakter harus didasarkan pada adaptor kami, karena hanya itu memberikan konversi karakter-ke-byte, apakah Anda menulis atau membaca, itu tidak dapat dipisahkan darinya.
Filereader kami tidak memperluas metode sendiri. Metode operasi karakter yang telah diimplementasikan dalam inputStreamReader kelas induk sudah cukup untuknya. Dia hanya perlu lulus dalam instance aliran byte yang sesuai.
Hal yang sama berlaku untuk filewriter, saya tidak akan membahas detail di sini.
Karakter Array Stream Chararrayreader/Writer
Array karakter dan aliran array byte serupa, baik untuk menyelesaikan situasi di mana ada ukuran file yang tidak pasti dan membutuhkan membaca sejumlah besar konten.
Karena mereka memberikan mekanisme ekspansi dinamis secara internal, mereka tidak hanya dapat mengakomodasi file target, tetapi juga mengontrol ukuran array agar tidak mengalokasikan terlalu banyak memori dan membuang banyak ruang memori.
Ambil ChararrayReader sebagai contoh
Lindung char buf []; public chararrayreader (char buf []) {this.buf = buf; this.pos = 0; this.count = buf.length;} public chararrayreader (char buf [], int offset, int int) {// ..}Tugas inti dari konstruktor adalah menginisialisasi array karakter ke atribut BUF internal. Semua operasi baca berikutnya pada contoh array stream karakter akan didasarkan pada array karakter buf.
Mengenai metode lain dari Chararrayreader dan Chararraywriter, saya tidak akan mengulanginya di sini, yang pada dasarnya mirip dengan aliran array byte di artikel sebelumnya.
Selain itu, ada juga StringReader dan StringWriter yang terlibat. Faktanya, pada dasarnya sama dengan aliran array karakter. Bagaimanapun, esensi string adalah array char.
BufferedReader/Writer
Demikian pula, BufferedReader/Writer adalah aliran buffer, dan juga merupakan aliran dekorator, digunakan untuk menyediakan fungsi buffering. Umumnya mirip dengan aliran buffer byte kami, mari kita perkenalkan secara singkat di sini.
pembaca pribadi di; char cb pribadi []; private static int defaultcharbufferSize = 8192; public bufferedReader (pembaca di, int sz) {..} public BufferedReader (pembaca di) {this (in, defaultCharbufferSize);}CB adalah array karakter yang menyimpan beberapa karakter yang dibaca dari aliran file. Anda dapat menginisialisasi panjang array ini dalam konstruktor, jika tidak nilai default 8192 akan digunakan.
Public int read () melempar ioException {..} public int read (char cbuf [], int off, int len) {...}Mengenai baca, itu tergantung pada metode baca atribut anggota. Sebagai tipe pembaca, di sering kali dibaca metode inputstream yang diandalkan secara internal.
Oleh karena itu, hampir semua aliran karakter tidak dapat dipisahkan dari contoh aliran byte.
Saya tidak akan mengulanginya di sini tentang BufferedWriter. Ini pada dasarnya serupa, kecuali bahwa yang satu membaca dan yang lainnya menulis, dan berkisar di sekitar array karakter internal.
Aliran cetak standar
Ada dua jenis utama aliran cetak, printstream dan printwriter. Yang pertama adalah aliran byte dan yang terakhir adalah aliran karakter.
Kedua aliran ini dianggap mengintegrasikan aliran di dalam kategori masing -masing. Ada metode enkapsulasi internal yang kaya, tetapi implementasinya juga agak rumit. Mari pertama -tama lihat aliran byte printstream:
Ada beberapa konstruktor utama:
Jelas, konstruktor sederhana akan mengandalkan konstruktor yang kompleks, yang sudah dianggap sebagai "rutin lama" untuk desain JDK. Yang membedakannya dari aliran byte lain adalah bahwa printstream menyediakan bendera autoflush yang menentukan apakah akan secara otomatis menyegarkan cache.
Berikutnya adalah metode penulisan printstream:
Selain itu, PrintStream juga merangkum sejumlah besar metode cetak dan menulis berbagai jenis konten ke dalam file, seperti:
Tentu saja, metode ini tidak benar -benar menulis biner numerik ke file, tetapi cukup tulis string yang sesuai untuk file, misalnya:
cetak (123);
File terakhir bukan pernyataan biner yang sesuai dengan 123, tetapi hanya string 123, yang merupakan aliran cetak.
Aliran karakter buffered yang digunakan oleh printstream mengimplementasikan semua operasi pencetakan. Jika refresh otomatis ditentukan, buffer akan disegarkan secara otomatis saat menemukan simbol garis baru "/n".
Jadi, PrintStream mengintegrasikan semua metode output dalam aliran byte dan aliran karakter, di mana metode tulis digunakan untuk operasi aliran byte dan metode cetak digunakan untuk operasi aliran karakter, yang perlu diklarifikasi.
Sedangkan untuk printwriter, ini adalah aliran karakter penuh yang beroperasi sepenuhnya terhadap karakter. Apakah itu metode tulis atau metode cetak, itu adalah operasi aliran karakter.
Singkatnya, kami menghabiskan tiga artikel yang menjelaskan aliran byte dan operasi aliran karakter di Java. Byte stream transmisi data lengkap antara disk dan memori berdasarkan byte. Yang paling khas adalah aliran karakter file, dan implementasinya adalah semua metode lokal. Dengan kemampuan transfer byte dasar, kami juga dapat meningkatkan efisiensi melalui buffering.
Implementasi paling dasar dari aliran karakter adalah InputStreamReader dan OutputStreamWriter. Secara teori, mereka sudah dapat menyelesaikan operasi aliran karakter dasar, tetapi mereka hanya terbatas pada operasi paling dasar. Apa yang diperlukan untuk membangun instance mereka adalah "instance aliran byte" + "format pengkodean".
Oleh karena itu, hubungan antara aliran karakter dan aliran byte sama seperti persamaan di atas. Langkah yang diperlukan untuk menulis karakter ke dalam file disk adalah mengkode karakter dalam format pengkodean yang ditentukan, dan kemudian menggunakan aliran byte untuk menulis biner karakter yang dikodekan ke file. Operasi yang dibaca adalah sebaliknya.
Semua kode, gambar, dan file dalam artikel disimpan di cloud di github saya:
(https://github.com/singleyam/overview_java)
Anda juga dapat memilih untuk mengunduh secara lokal.
Meringkaskan
Di atas adalah seluruh konten artikel ini. Saya berharap konten artikel ini memiliki nilai referensi tertentu untuk studi atau pekerjaan semua orang. Jika Anda memiliki pertanyaan, Anda dapat meninggalkan pesan untuk berkomunikasi. Terima kasih atas dukungan Anda ke wulin.com.