什么是I/O 流逮京,如何分類
Java的核心庫http://java.io提供了全面的I/O接口疯潭。所謂I/O其實(shí)是Input和Output的縮寫概说,在Java中,I/O指的是通過數(shù)據(jù)流震缭、序列化和文件系統(tǒng)提供系統(tǒng)的輸入和輸出赂毯。
Java中的I/O是以流為基礎(chǔ)實(shí)現(xiàn)輸入/輸出的,流是一個(gè)很形象的概念拣宰,當(dāng)程序需要讀取數(shù)據(jù)(Input)時(shí)党涕,就會(huì)開啟一個(gè)通向數(shù)據(jù)源的流,這個(gè)數(shù)據(jù)源可以是文件巡社、內(nèi)存膛堤,或者網(wǎng)絡(luò)連接;當(dāng)程序需要寫入數(shù)據(jù)(Output)時(shí)晌该,就會(huì)開啟一個(gè)通向目的地的流肥荔。數(shù)據(jù)好像在其中“流”動(dòng)一樣。所以朝群,我們會(huì)經(jīng)常聽到I/O流這樣的描述燕耿。
Java中的I/O是一個(gè)非常龐大的體系,下面介紹I/O流的分類姜胖。
I/O流的分類方式有許多種缸棵,按照流的方向可以分為輸入流和輸出流;按照數(shù)據(jù)傳輸?shù)膯挝挥挚梢詣澐譃樽止?jié)流和字符流谭期。
1. 輸入流與輸出流
對(duì)于輸入和輸出堵第,需要有一個(gè)參照物,我們?cè)诿枋隽鞯姆较驎r(shí)隧出,可以把外部輸入設(shè)備作為參照物踏志。
當(dāng)程序要從外部輸入設(shè)備,如文件胀瞪、網(wǎng)絡(luò)等讀取數(shù)據(jù)時(shí)针余,流的方向是外部輸入設(shè)備到運(yùn)行程序饲鄙,這種方向的I/O流我們稱之為輸入流。
當(dāng)程序要把數(shù)據(jù)寫入外部輸入設(shè)備時(shí)圆雁,流的方向是運(yùn)行程序到外部設(shè)備忍级,這種方向的I/O流我們稱之為輸出流,如圖14-1所示伪朽。
2. 字節(jié)與字符
I/O流的作用是傳輸數(shù)據(jù)轴咱,根據(jù)數(shù)據(jù)傳輸?shù)膯挝豢梢园袸/O流分為字節(jié)流和字符流。那么什么是字節(jié)和字符呢烈涮?
在計(jì)算機(jī)中朴肺,數(shù)據(jù)的最小單位是比特(bit),比特是信息技術(shù)中最基本的存儲(chǔ)單元坚洽,二進(jìn)制中的一位就是1 bit戈稿。
但是因?yàn)楸忍靥×耍晕覀兺ǔT谟?jì)量數(shù)據(jù)容量時(shí)讶舰,會(huì)采用字節(jié)(Byte)這種計(jì)量單位鞍盗。在大多數(shù)計(jì)算機(jī)系統(tǒng)中,一個(gè)字節(jié)(Byte)是一個(gè)8位(bit)長的數(shù)據(jù)單位跳昼,所以Byte和bit之間的換算關(guān)系是 1 Byte=8 bit 橡疼。
通常我們也把Byte縮寫成B,隨著存儲(chǔ)容量越來越大庐舟,我們也經(jīng)常使用KB欣除、MB、GB挪略、TB等表示數(shù)據(jù)容量历帚。
除了以字節(jié)為傳輸單位,還有一種常見的傳輸方式——傳輸字符杠娱。
字符(Char挽牢,Character)是計(jì)算機(jī)中使用的字母、數(shù)字摊求、字和符號(hào)禽拔,比如A、B室叉、1睹栖、$等。
一般情況下茧痕,一個(gè)英文字符占用1字節(jié)野来,一個(gè)漢字字符占用2字節(jié)。這只是通常的情況踪旷,因?yàn)樵诓煌木幋a方式下曼氛,字符占用的字節(jié)數(shù)是不一定的豁辉,關(guān)于這部分知識(shí),我們?cè)诘?3章中會(huì)重點(diǎn)介紹舀患。
因?yàn)橐粋€(gè)字符至少要占用1字節(jié)徽级,所以字符是比字節(jié)更大的一種計(jì)量單位。
3. 字節(jié)流與字符流
在I/O流中聊浅,傳輸?shù)臄?shù)據(jù)類型是字節(jié)(Byte)的就是字節(jié)流餐抢,傳輸?shù)臄?shù)據(jù)類型是字符(Char)的就是字符流。
在Java中狗超,操作字節(jié)類型的數(shù)據(jù)的主要操作類是OutputStream和InputStream的子類,操作字符類型的數(shù)據(jù)的主要操作類是Reader和Writer的子類朴下。
如果按照流向來區(qū)分這四種類努咐,那么InputStream和Reader是輸入流,而OutputStream和Writer是輸出流殴胧,如表所示渗稍。
4. 字節(jié)流與字符流的互相轉(zhuǎn)換
在Java的I/O體系中,除了字節(jié)流团滥、字符流需要用的這四種I/O相關(guān)的類竿屹,還存在一組字節(jié)流—字符流的轉(zhuǎn)換類。也就是說灸姊,字節(jié)流和字符流之間是可以相互轉(zhuǎn)換的拱燃,當(dāng)我們想要把字符流轉(zhuǎn)成字節(jié)流時(shí),可以使用OutputStreamWriter力惯;當(dāng)我們想要把字節(jié)流轉(zhuǎn)成字符流時(shí)碗誉,可以使用InputStreamReader。
OutputStreamWriter:Writer的子類父晶,是字符流通向字節(jié)流的橋梁哮缺,將輸出的字符流變?yōu)樽止?jié)流,即將一個(gè)字符流的輸出對(duì)象變?yōu)樽止?jié)流輸出對(duì)象甲喝。其用法如下:
public static void main(String[] args) throws IOException {
File f = new File("io.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(f),"UTF-8");
osw.write(" 字符轉(zhuǎn)成字節(jié)輸出");
osw.close();
}
InputStreamReader:Reader的子類尝苇,是字節(jié)流通向字符流的橋梁,將輸入的字節(jié)流變?yōu)樽址鞑号郑磳⒁粋€(gè)字節(jié)流的輸入對(duì)象變?yōu)樽址鞯妮斎雽?duì)象糠溜。其用法如下:
public static void main(String[] args) throws IOException {
File f = new File("io.txt");
InputStreamReader inr = new InputStreamReader(new FileInputStream(f),"UTF-8");
char[] buf = new char[1024];
int len = inr.read(buf);
System.out.println(new String(buf,0,len));
inr.close();
}