簡(jiǎn)介
- 流:流代表任何有能力產(chǎn)生數(shù)據(jù)的數(shù)據(jù)源對(duì)象或有能力接收數(shù)據(jù)的接收端對(duì)象递沪,如文件丸冕、網(wǎng)絡(luò)延赌、內(nèi)存等除盏。
- Java I/O 類庫(kù)的設(shè)計(jì)中采用了裝飾器模式和適配器模式
- Java I/O 類庫(kù)中的裝飾器模式:FilterInputStream和FilterOutputStream類是Java I/O 類庫(kù)中所有裝飾器的抽象基類,這兩個(gè)類繼承自InputStream和OutputStream挫以,都只是簡(jiǎn)單地重寫了父類中的方法者蠕,而并未提供新功能。通過其子類為被包裝對(duì)象提供新功能掐松。裝飾器模式的使用使得Java I/O 類庫(kù)不那么容易使用踱侣,一般在進(jìn)行I/O操作時(shí),都會(huì)創(chuàng)建不止一個(gè) I/O 對(duì)象甩栈,通過層層包裝泻仙,最后才會(huì)獲得我們真正想要進(jìn)行 I/O 操作的對(duì)象糕再。
如下面這個(gè)示例量没,為了創(chuàng)建一個(gè)DataInputStream 對(duì)象 從名為"filename"的文件中獲取數(shù)據(jù),首先創(chuàng)建了一個(gè)FileInputStream對(duì)象突想,然后創(chuàng)建了一個(gè)包裝這個(gè)FileInputStream對(duì)象的BufferedInputStream對(duì)象殴蹄,最后通過將BufferedInputStream對(duì)象傳給DataInputStream,才獲得我們真正想要獲得的結(jié)果對(duì)象猾担。
DataInputStream in = new DataInputStream(
new BufferedInputStream(
new FileInputStream("filename")));
- Java I/O 類庫(kù)中的適配器模式:InputStreamReader和OutputStreamWriter這兩個(gè)類可以完成“字節(jié)流”和“字符流”之間的適配袭灯,通過使用這兩個(gè)類,就可以將面向“字節(jié)流”的InputStream和OutputStream轉(zhuǎn)化為面向“字符流”的Reader和Writer绑嘹。
InputStream & OutputStream
- Java最開始的 I/O 類庫(kù)設(shè)計(jì)都是面向字節(jié)流的稽荧,所以在 JDK 1.0 中,I/O 類庫(kù)主要分為兩部分:所有與輸入有關(guān)的類都繼承自 InputStream工腋,所有與輸出有關(guān)的類都繼承自 OutputStream姨丈,InputStream和OutputStream是這些類的抽象基類畅卓。
- InputStream用于表示那些從不同的數(shù)據(jù)源產(chǎn)生輸入的類,這些輸入源主要有:字節(jié)數(shù)組蟋恬、String對(duì)象翁潘、文件、“管道”歼争、一個(gè)由其他的流所組成的序列拜马、其他數(shù)據(jù)源(Internet等)
- OutputStream主要用于將數(shù)據(jù)向目標(biāo)輸出,如向文件沐绒、內(nèi)存俩莽、字節(jié)數(shù)組、網(wǎng)絡(luò)等輸出數(shù)據(jù)
下面兩圖展示了InputStream和OutputStream類層次關(guān)系乔遮,可以看到這兩個(gè)類中包含的子類基本上呈現(xiàn)一一對(duì)應(yīng)的模式豹绪。
InputStream
OutputStream
- FilterInputStream和FilterOutputStream為“裝飾器”類提供了一個(gè)基類,用于將屬性或有用的接口分別與輸入/輸出流連接起來申眼。
Reader & Writer
- Java 1.1對(duì)基本的 I/O流類庫(kù)進(jìn)行了重大修改瞒津,添加了一個(gè)面向Unicode字符的Reader和Writer類。設(shè)計(jì)Reader & Writer的目的在于國(guó)際化:舊的InputStream & OutputStream類庫(kù)只能支持8為字節(jié)操作括尸,不能很好地處理16位Unicode字符巷蚪。而16位Unicode字符用于字符國(guó)際化(Java本身的char也是16位Unicode字符),所以添加Reader & Writer繼承層次結(jié)構(gòu)就是為了在所有的I/O操作中都支持Unicode濒翻。同時(shí)新類庫(kù)也比舊類庫(kù)快屁柏。
- 當(dāng)需要將面向字節(jié)的流與面向字符的流結(jié)合使用時(shí),可以使用Java I/O類庫(kù)中的適配器類:InputStreamReader和OutputStreamWriter有送,通過這兩個(gè)類分別將InputStream和OutputStream轉(zhuǎn)化為Reader和Writer淌喻。
下面兩圖展示了Reader和Writer類層次關(guān)系:
Reader
Writer
下表展示了在這兩個(gè)繼承層次結(jié)構(gòu)中數(shù)據(jù)來源與去向間的一一對(duì)應(yīng)關(guān)系:
類對(duì)應(yīng)關(guān)系表
過濾器對(duì)應(yīng)關(guān)系表
RandomAccessFile
- RandomAccessFile是一個(gè)完全獨(dú)立的類,直接繼承自O(shè)bject雀摘,并且實(shí)現(xiàn)了DataOutput和DataInput接口裸删。RandomAccessFile主要適用于由大小已知的記錄所組成的文件,這樣就可以使用seek()方法將記錄從一處移到另一處阵赠。
- 在 JDK 1.4中涯塔,RandomAccessFile的大多數(shù)功能由nio中的存儲(chǔ)映射文件所取代。
// RandomAccessFile的使用
public class RandomAccessFileTest {
static void display(RandomAccessFile read) throws IOException {
byte[] bytes = new byte[16];
read.seek(0);
read.read(bytes);
for (int j = 0; j < bytes.length; j++) {
printnb((char) bytes[j]);
}
print();
print(read.readBoolean());
print(read.readInt());
print(read.readUTF());
}
public static void main(String[] args) throws IOException {
String filename = "raf";
RandomAccessFile read = new RandomAccessFile(filename, "r");
RandomAccessFile write = new RandomAccessFile(filename, "rw");
//執(zhí)行write操作清蚀,向文件--raf中寫入數(shù)據(jù)
write.seek(0);
write.writeBytes("RandomAccessFile");
write.writeBoolean(true);
write.writeInt(123);
write.writeUTF("End writing");
display(read); // 顯示寫入文件中的數(shù)據(jù)
write.seek(2); // 將“光標(biāo)”移到文件的第二個(gè)字節(jié)處
write.writeChar('k'); // 在“光標(biāo)”當(dāng)前位置寫入字符'k'
display(read);
// 關(guān)閉文件
read.close();
write.close();
}
}
//Output:
RandomAccessFile
true
123
End writing
Ra komAccessFile // 一個(gè)字符占兩個(gè)字節(jié)匕荸,所以文件的第二、三個(gè)字節(jié)用于寫入字符'k'
true
123
End writing
注:
- 正如上面的代碼所示枷邪,在使用RandomAccessFile時(shí)榛搔,一般需要預(yù)先知道文件的排版,這樣才能正確地操作這個(gè)文件,并很好的利用其隨機(jī)訪問的功能
- 裝飾器模式:裝飾模式也稱之為包裝器模式(Wrapper)践惑,是一種為已有的功能動(dòng)態(tài)添加新功能的方式绑洛,它把每個(gè)要裝飾的功能都放在一個(gè)單獨(dú)的類中,并讓這個(gè)類包裝它所要裝飾的對(duì)象童本,因此真屯,當(dāng)需要執(zhí)行某些特殊的行為時(shí),客戶端代碼就可以根據(jù)需要有選擇的穷娱、按順序的使用裝飾功能包裝對(duì)象绑蔫。
優(yōu)點(diǎn):把類中的核心職責(zé)和裝飾功能區(qū)分開來,可以有效去除相關(guān)類中的重復(fù)裝飾邏輯代碼泵额。
缺點(diǎn):需要添加一些額外的裝飾器代碼配深,代碼結(jié)構(gòu)相對(duì)比較復(fù)雜。