一欺税、IO流整體結(jié)構(gòu)圖
流是一組有順序的,有起點和終點的字節(jié)集合欲虚,是對數(shù)據(jù)傳輸?shù)目偡Q或抽象集灌。即數(shù)據(jù)在兩設(shè)備間的傳輸稱為流,流的本質(zhì)是數(shù)據(jù)傳輸复哆,根據(jù)數(shù)據(jù)傳輸特性將流抽象為各種類欣喧,方便更直觀的進(jìn)行數(shù)據(jù)操作。
字符流和字節(jié)流
字符流的由來: 因為數(shù)據(jù)編碼的不同梯找,而有了對字符進(jìn)行高效操作的流對象唆阿。本質(zhì)其實就是基于字節(jié)流讀取時,去查了指定的碼表锈锤。 字節(jié)流和字符流的區(qū)別:
讀寫單位不同:字節(jié)流以字節(jié)(8bit)為單位驯鳖,字符流以字符為單位闲询,根據(jù)碼表映射字符,一次可能讀多個字節(jié)浅辙。
處理對象不同:字節(jié)流能處理所有類型的數(shù)據(jù)(如圖片扭弧、avi等),而字符流只能處理字符類型的數(shù)據(jù)记舆。
結(jié)論:只要是處理純文本數(shù)據(jù)鸽捻,就優(yōu)先考慮使用字符流。 除此之外都使用字節(jié)流泽腮。
二御蒲、字符流
字符流輸入輸出關(guān)系對應(yīng)
字符輸入流Reader
Reader 是所有的輸入字符流的父類,它是一個抽象類盛正。
CharReader删咱、StringReader 是兩種基本的介質(zhì)流,它們分別將Char 數(shù)組豪筝、String中讀取數(shù)據(jù)痰滋。PipedReader 是從與其它線程共用的管道中讀取數(shù)據(jù)。
BufferedReader 很明顯就是一個裝飾器续崖,它和其子類負(fù)責(zé)裝飾其它Reader 對象敲街。
FilterReader 是所有自定義具體裝飾流的父類,其子類PushbackReader 對Reader 對象進(jìn)行裝飾严望,會增加一個行號多艇。
InputStreamReader 是一個連接字節(jié)流和字符流的橋梁,它將字節(jié)流轉(zhuǎn)變?yōu)樽址飨裎恰ileReader 可以說是一個達(dá)到此功能峻黍、常用的工具類,在其源代碼中明顯使用了將FileInputStream 轉(zhuǎn)變?yōu)镽eader 的方法拨匆。我們可以從這個類中得到一定的技巧姆涩。Reader 中各個類的用途和使用方法基本和InputStream 中的類使用一致。
字符輸出流Writer
Writer 是所有的輸出字符流的父類惭每,它是一個抽象類骨饿。
CharArrayWriter、StringWriter 是兩種基本的介質(zhì)流台腥,它們分別向Char 數(shù)組宏赘、String 中寫入數(shù)據(jù)。PipedWriter 是向與其它線程共用的管道中寫入數(shù)據(jù)黎侈,
BufferedWriter 是一個裝飾器為Writer 提供緩沖功能察署。
PrintWriter 和PrintStream 極其類似,功能和使用也非常相似峻汉。
OutputStreamWriter 是OutputStream 到Writer 轉(zhuǎn)換的橋梁箕母,它的子類FileWriter 其實就是一個實現(xiàn)此功能的具體類(具體可以研究一SourceCode)储藐。功能和使用和OutputStream 極其類似,
1嘶是、FileWriter和FileReader
1)FileWriter
/**
* 字符流FileWriter
* @author Administrator
*
*/
publicclassFileWriterDemo{
publicstaticvoidmain(String[]args){
try{
/*
* 1钙勃、創(chuàng)建FileWriter對象,該對象在初始化時就必須明確被操作的文件
* 而且該文件將被創(chuàng)建到指定目錄下聂喇,若該文件已經(jīng)存在辖源,則將其覆蓋
* 否則,進(jìn)行創(chuàng)建希太。
*/
Filefile=newFile("files/writerFile.txt");
FileWriterfileWriter=newFileWriter(file);
//true表示不覆蓋已有文件克饶,而是直接在文件末尾續(xù)寫
FileWriterfWriter=newFileWriter(file,false);
/*
* 2、調(diào)用write方法誊辉,將字符串寫入到流中
*/
fileWriter.write("hello矾湃,你好!");
/*
* 3堕澄、刷新流對象緩存中的數(shù)據(jù)邀跃,將數(shù)據(jù)刷新到目的地中
*/
fileWriter.flush();
/*
* 4、關(guān)閉資源蛙紫,在關(guān)閉之前拍屑,會刷新一次流對象緩存中的數(shù)據(jù),將其保存到目的地坑傅。
*/
fileWriter.close();
fWriter.write("hellohello!");
fWriter.flush();
fWriter.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
2)FileReader
/**
* 字符流FileReader
* @author Administrator
*
*/
publicclassFileReaderDemo{
publicstaticvoidmain(String[]args){
try{
//1僵驰、創(chuàng)建一個文件讀取流對象,和指定名稱的文件相關(guān)聯(lián)
//? 要保證該文件一定存在唁毒,否則會報FileNotFoundException
Filefile=newFile("files/writerFile.txt");
FileReaderfileReader=newFileReader(file);
//2蒜茴、調(diào)用read方法讀取流對象,一次讀一個字符浆西,而且會自動往下讀
try{
char[]ch=newchar[100];
inttemp=0;
intcount=0;
//-1表示讀到了文件末尾
while((temp=fileReader.read())!=-1){
ch[count++]=(char)temp;
}
Stringfiles=newString(ch,0,count);
System.out.println(files);
}catch(IOExceptione){
e.printStackTrace();
}
//3粉私、關(guān)閉資源
try{
fileReader.close();
}catch(IOExceptione){
e.printStackTrace();
}
}catch(FileNotFoundExceptione){
e.printStackTrace();
}
}
}
2、BufferedWriter和BufferedReader
緩沖區(qū)室谚,是為了提高流的操作效率而產(chǎn)生毡鉴,所以在創(chuàng)建緩沖區(qū)之前必須先有流對象崔泵,這種模式叫做裝飾模式秒赤,比繼承靈活,避免了繼承的臃腫憎瘸。
1)BufferedWriter
/**
* 字符流BufferedWriter
* @author Administrator
*
*/
publicclassBufferedWriterDemo{
publicstaticvoidmain(String[]args){
try{
//1入篮、創(chuàng)建一個字符寫入流對象
Filefile=newFile("files/writerFile.txt");
FileWriterfileWriter=newFileWriter(file,true);
//2、為了提高寫入效率幌甘,加入緩沖技術(shù)
//? 只需將需要提高效率的流對象作為參數(shù)傳給緩沖區(qū)的構(gòu)造函數(shù)即可
BufferedWriterbufferedWriter=newBufferedWriter(fileWriter);
//3潮售、調(diào)用write方法痊项,將字符串寫入緩沖中
//bufferedWriter.write("汪小峰,汪小峰");
for(inti=0;i<4;i++){
bufferedWriter.write("abcde"+i);
//進(jìn)行換行操作
bufferedWriter.newLine();
//刷新
//bufferedWriter.flush();
}
//4酥诽、刷新鞍泉,只要用到緩沖區(qū),就必須進(jìn)行刷新操作
bufferedWriter.flush();
//5肮帐、關(guān)閉資源
bufferedWriter.close();
fileWriter.close();
}catch(FileNotFoundExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
2)BufferedReader
/**
* 字符流BufferedReader
* @author Administrator
*
*/
publicclassBufferedReaderDemo{
publicstaticvoidmain(String[]args){
try{
//1咖驮、創(chuàng)建一個讀取的流對象
Filefile=newFile("files/writerFile.txt");
FileReaderfileReader=newFileReader(file);
//2、為了提高效率训枢,加入緩沖技術(shù)托修,將字符讀取流對象作為參數(shù)傳遞給緩沖構(gòu)造器
BufferedReaderbufferedReader=newBufferedReader(fileReader);
//3、調(diào)用readLine方法恒界,讀緩沖中的數(shù)據(jù)睦刃,一行一行的讀入
Stringline=null;
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
//4、關(guān)閉資源
fileReader.close();
}catch(FileNotFoundExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
3十酣、OutputStreamWriter和InputStreamReader
轉(zhuǎn)換流是字節(jié)流和字符流之間的橋梁涩拙,通常,在涉及到字符編碼轉(zhuǎn)換時應(yīng)用婆誓。
InputStreamReader:字節(jié)到字符的橋梁
OutputStreamWriter:字符到字節(jié)的橋梁
1)OutputStreamWriter
/**
* 轉(zhuǎn)換流OutputStreamWriter
* @author wxf
*
*/
publicclassOutputStreamWriterDemo{
publicstaticvoidmain(String[]args){
/*
//1吃环、創(chuàng)建字節(jié)流對象
OutputStream outputStream = System.out;
//2、將字節(jié)流對象轉(zhuǎn)換成字符流對象
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
//3洋幻、加入緩沖技術(shù)郁轻,提高效率
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
*/
//通常將以上三步簡寫為
BufferedWriterbufferedWriter=newBufferedWriter(newOutputStreamWriter(System.out));
//4、調(diào)用write方法文留,將將字符串寫入緩沖中
for(inti=0;i<4;i++){
try{
bufferedWriter.write("wangxf"+i);
//換行
bufferedWriter.newLine();
//5好唯、刷新
bufferedWriter.flush();
}catch(IOExceptione){
e.printStackTrace();
}
}
//6、關(guān)閉資源
try{
bufferedWriter.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
2)InputStreamReader
/**
* 轉(zhuǎn)換流InputStreamReader
* @author wxf
*
*/
publicclassInputStreamReaderDemo{
publicstaticvoidmain(String[]args){
/*
//1燥翅、創(chuàng)建字節(jié)流對象,獲取鍵盤錄入對象
InputStream inputStream = System.in;
//2骑篙、將字節(jié)流轉(zhuǎn)換成字符流
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
//3、加入緩沖技術(shù)
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
*/
//一般將以上三步簡寫為
BufferedReaderbufferedReader=newBufferedReader(newInputStreamReader(System.in));
//4森书、調(diào)用readLine方法讀取流對象信息
Stringline=null;
try{
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
}catch(IOExceptione){
e.printStackTrace();
}
//5靶端、關(guān)閉資源
try{
bufferedReader.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
通過字符流讀取鍵盤輸入的字符時,通過ctrl+z來結(jié)束凛膏。
三杨名、字節(jié)流
字節(jié)流輸入輸出對應(yīng)關(guān)系
圖中藍(lán)色的為主要的對應(yīng)部分,紅色的部分就是不對應(yīng)部分猖毫。紫色的虛線部分代表這些流一般要搭配使用台谍。
LineNumberInputStream 主要完成從流中讀取數(shù)據(jù)時,會得到相應(yīng)的行號吁断,至于什么時候分行趁蕊、在哪里分行是由改類主動確定的坞生,并不是在原始中有這樣一個行號。在輸出部分沒有對應(yīng)的部分掷伙,我們完全可以自己建立一個LineNumberOutputStream是己,在最初寫入時會有一個基準(zhǔn)的行號,以后每次遇到換行時會在下一行添加一個行號任柜,看起來也是可以的赃泡。好像更不入流了。
PushbackInputStream 的功能是查看最后一個字節(jié)乘盼,不滿意就放入緩沖區(qū)升熊。主要用在編譯器的語法、詞法分析部分绸栅。輸出部分的BufferedOutputStream 幾乎實現(xiàn)相近的功能级野。
StringBufferInputStream 已經(jīng)被Deprecated,本身就不應(yīng)該出現(xiàn)在InputStream 部分粹胯,主要因為String 應(yīng)該屬于字符流的范圍蓖柔。已經(jīng)被廢棄了,當(dāng)然輸出部分也沒有必要需要它了风纠!還允許它存在只是為了保持版本的向下兼容而已况鸣。
SequenceInputStream 可以認(rèn)為是一個工具類,將兩個或者多個輸入流當(dāng)成一個輸入流依次讀取竹观。完全可以從IO 包中去除镐捧,還完全不影響IO 包的結(jié)構(gòu),卻讓其更“純潔”――純潔的Decorator 模式臭增。
PrintStream 也可以認(rèn)為是一個輔助工具懂酱。主要可以向其他輸出流,或者FileInputStream 寫入數(shù)據(jù)誊抛,本身內(nèi)部實現(xiàn)還是帶緩沖的列牺。本質(zhì)上是對其它流的綜合運用的一個工具而已。一樣可以踢出IO 包拗窃!System.out 和System.out 就是PrintStream 的實例瞎领!
輸入字節(jié)流InputStream
InputStream 是所有的輸入字節(jié)流的父類,它是一個抽象類随夸。
ByteArrayInputStream九默、StringBufferInputStream、FileInputStream 是三種基本的介質(zhì)流逃魄,它們分別從Byte 數(shù)組荤西、StringBuffer澜搅、和本地文件中讀取數(shù)據(jù)伍俘。PipedInputStream 是從與其它線程共用的管道中讀取數(shù)據(jù)邪锌,與Piped 相關(guān)的知識后續(xù)單獨介紹。
ObjectInputStream 和所有FilterInputStream 的子類都是裝飾流(裝飾器模式的主角)癌瘾。
輸出字節(jié)流OutputStream
OutputStream 是所有的輸出字節(jié)流的父類觅丰,它是一個抽象類。
ByteArrayOutputStream妨退、FileOutputStream 是兩種基本的介質(zhì)流妇萄,它們分別向Byte 數(shù)組、和本地文件中寫入數(shù)據(jù)咬荷。PipedOutputStream 是向與其它線程共用的管道中寫入數(shù)據(jù)冠句,
ObjectOutputStream 和所有FilterOutputStream 的子類都是裝飾流。
1幸乒、OutputStream和InputStream
1)FileOutputStream
/**
* 字節(jié)流FileOutputStream
* @author wxf
*
*/
publicclassFileOutputStreamDemo{
publicstaticvoidmain(String[]args){
//1懦底、創(chuàng)建字節(jié)流對象
Filefile=newFile("files/iofiles.txt");
FileOutputStreamfileOutputStream=null;
try{
fileOutputStream=newFileOutputStream(file);
}catch(FileNotFoundExceptione){
e.printStackTrace();
}
//2、調(diào)用write方法寫入字節(jié)
byte[]b=newbyte[10];
for(inti=0;i<10;i++){
b[i]='a';
}
try{
fileOutputStream.write(b,0,b.length);
}catch(IOExceptione){
e.printStackTrace();
}
//3罕扎、刷新
try{
fileOutputStream.flush();
}catch(IOExceptione){
e.printStackTrace();
}
//4聚唐、關(guān)閉資源
try{
fileOutputStream.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
2)FileInputStream
/**
* 字節(jié)流FileInputStream
* @author wxf
*
*/
publicclassFileInputStreamDemo{
publicstaticvoidmain(String[]args){
//1、創(chuàng)建流對象
Filefile=newFile("files/iofiles.txt");
FileInputStreamfileInputStream=null;
try{
fileInputStream=newFileInputStream(file);
}catch(FileNotFoundExceptione){
e.printStackTrace();
}
//2腔召、調(diào)用read方法杆查,讀入字節(jié)
byte[]bs=newbyte[10];
inttemp=0;
intcuont=0;
try{
while((temp=fileInputStream.read())!=-1){
bs[cuont++]=(byte)temp;
System.out.println(cuont);
}
Stringstring=newString(bs);
System.out.println(string);
}catch(IOExceptione){
e.printStackTrace();
}
//3、關(guān)閉資源
try{
fileInputStream.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
四臀蛛、File類
File類是對文件系統(tǒng)中文件以及文件夾進(jìn)行封裝的對象亲桦,可以通過對象的思想來操作文件和文件夾。 File類保存文件或目錄的各種元數(shù)據(jù)信息浊仆,包括文件名烙肺、文件長度、最后修改時間氧卧、是否可讀桃笙、獲取當(dāng)前文件的路徑名,判斷指定文件是否存在沙绝、獲得當(dāng)前目錄中的文件列表搏明,創(chuàng)建、刪除文件和目錄等方法闪檬。
五星著、RandomAccessFile類
該對象并不是流體系中的一員,其封裝了字節(jié)流粗悯,同時還封裝了一個緩沖區(qū)(字符數(shù)組)虚循,通過內(nèi)部的指針來操作字符數(shù)組中的數(shù)據(jù)。 該對象特點:
該對象只能操作文件,所以構(gòu)造函數(shù)接收兩種類型的參數(shù):a.字符串文件路徑横缔;b.File對象铺遂。
該對象既可以對文件進(jìn)行讀操作,也能進(jìn)行寫操作茎刚,在進(jìn)行對象實例化時可指定操作模式(r,rw)
注意:該對象在實例化時襟锐,如果要操作的文件不存在,會自動創(chuàng)建膛锭;如果文件存在粮坞,寫數(shù)據(jù)未指定位置,會從頭開始寫初狰,即覆蓋原有的內(nèi)容莫杈。可以用于多線程下載或多個線程同時寫數(shù)據(jù)到文件。
注:該文章是本人在搜集網(wǎng)上資料后總結(jié)而成奢入,主要參考博客園-殘夜姓迅,以及簡書-Quora
有更好的資料或者見解,希望不吝賜教俊马。