學(xué)習(xí)目的
- 了解java流的概念
- 了解java對(duì)流的分類(lèi)
- 掌握java流的對(duì)象創(chuàng)建,以及常用方法的使用
- 掌握java流常見(jiàn)的應(yīng)用場(chǎng)景
- 掌握重點(diǎn)流:FileStream意敛、PrintStream、ObjectStream
- 了解序列化與反序列化的概念和使用
I/O流
概念
流 在java中指的是文件的轉(zhuǎn)移過(guò)程,通常是指文件在計(jì)算機(jī)硬盤(pán)和計(jì)算機(jī)內(nèi)存之間的傳遞方式鸠按。該傳遞過(guò)程包括了文件數(shù)據(jù)和方向。-
字節(jié)流繼承結(jié)構(gòu)圖
InputStream 和 OutputStream 繼承結(jié)構(gòu)圖.png -
字符流繼承結(jié)構(gòu)圖
Reader 和 Writer 繼承結(jié)構(gòu)圖.png 流與文件路徑
輸入流對(duì)文件的讀取和輸出流對(duì)文件的寫(xiě)入柳洋,都需要提前知道文件的路徑在哪待诅,一般使用相對(duì)路徑和絕對(duì)路徑來(lái)存儲(chǔ)文件。
- 相對(duì)路徑:在IDEA或eclipse中熊镣,相對(duì)路徑是項(xiàng)目/工程的根目錄卑雁,即項(xiàng)目所在的路徑就是相對(duì)路徑。項(xiàng)目工程所在的根目錄才是相對(duì)路徑起點(diǎn)绪囱,注意項(xiàng)目底下的子模塊路徑不是相對(duì)路徑的起點(diǎn)测蹲;
- 絕對(duì)路徑:絕對(duì)路徑是任意盤(pán)符下所保存的文件路徑,引用絕對(duì)路徑的文件時(shí)鬼吵,必須將絕對(duì)路徑從盤(pán)符開(kāi)始具體寫(xiě)明扣甲。
1、 IO流與Properties
- .properties文件
以.properties為后綴名的文件是java中的屬性配置文件齿椅,通常存儲(chǔ)一些可改變的配置信息琉挖。該文件的存儲(chǔ)內(nèi)容與其后綴名一樣,采用properties集合存儲(chǔ)key=value涣脚,即采用Map的鍵值對(duì)形式存儲(chǔ)示辈,且properties的鍵與值得類(lèi)型只能為String類(lèi)型。在properties文件中允許key重復(fù)遣蚀,但key重復(fù)時(shí)矾麻,會(huì)覆蓋value值。 - .properties文件原由
在開(kāi)發(fā)中芭梯,經(jīng)常遇到改變頻繁的數(shù)據(jù)险耀,因此可以將這些數(shù)據(jù)單獨(dú)寫(xiě)到一個(gè)配置文件中,使用程序動(dòng)態(tài)讀取玖喘。將來(lái)只需要修改這個(gè)文件的數(shù)據(jù)內(nèi)容甩牺,java代碼不需要改動(dòng),不需要重新編譯累奈,服務(wù)器也不需要重啟贬派,就可以拿到動(dòng)態(tài)的信息。 - IO讀取.properties文件
將.properties文件作為一個(gè)File對(duì)象费尽,使用輸入流來(lái)讀取該文件的內(nèi)容赠群,就可以獲取得到需要的配置信息羊始,可以讓配置信息更加靈活多變旱幼,且不會(huì)觸及修改java源代碼(修改違背開(kāi)閉原則)。 - 示例(假設(shè)已存在對(duì)應(yīng)的.properties文件)
//Properties是一個(gè)Map集合突委,key和value都是String類(lèi)型
//將XXX.properties文件中的數(shù)據(jù)讀取柏卤,就是加載到Properties對(duì)象當(dāng)中
// 新建一個(gè)輸入流對(duì)象
FileReader reader = new FileReader("路徑\\XXX.properties");
// 新建一個(gè)Map集合(具體是Hashtable的子類(lèi)Properties)
Properties pro = new Properties();
// 調(diào)用Properties對(duì)象的load方法將屬性配置文件中的數(shù)據(jù)加載到Map集合中
pro.load(reader); // 文件中的數(shù)據(jù)順著管道加載到Map集合中
// 通過(guò)Properties的key來(lái)獲取對(duì)應(yīng)value
String username = pro.getProperty("username");
System.out.println(username);
一.字節(jié)字符流
流概念
文件由字符或字節(jié)構(gòu)成冬三,將文件加載到內(nèi)存 或 將內(nèi)存數(shù)據(jù)輸出到文件,需要有輸入和輸出流的支持缘缚。因此可以把輸入和輸出流分為了兩個(gè)勾笆,字節(jié)輸入 和 字符輸入,字節(jié)輸出流 和 字符輸出流桥滨。以流的方向分類(lèi)
- 輸入流:Input窝爪,Java中 將文件或其它輸入設(shè)備的數(shù)據(jù) 從硬盤(pán)加載到內(nèi)存的過(guò)程;
- 輸出流:Output齐媒,Java中 將內(nèi)存中的數(shù)據(jù) 保存到硬盤(pán)中的文件或其他輸出設(shè)備的過(guò)程蒲每。
- 以讀取文件數(shù)據(jù)的方式分類(lèi)
- 字節(jié)流Stream:以Stream結(jié)尾命名的流都是字節(jié)流,字節(jié)流一次讀取1個(gè)字節(jié)byte(即8個(gè)二進(jìn)制位)喻括。
- 字符流Reader邀杏、Writer:以Reader或Writer 結(jié)尾命名的流都是字符流,字符流一次讀取一個(gè)字符char(兩個(gè)字節(jié)16個(gè)二進(jìn)制位)唬血。
-
流關(guān)系圖
流關(guān)系圖.png - 區(qū)別
- 字節(jié)流:每次讀取一個(gè)字節(jié)望蜡,使用byte[]數(shù)組存儲(chǔ)、讀寫(xiě)多個(gè)字節(jié)拷恨;
- 字符流:每次讀取一個(gè)字符脖律,流本身自帶并使用char[]數(shù)組存儲(chǔ)、讀寫(xiě)多個(gè)字符挑随。
1.1 字節(jié)輸入流<InputStream>
概念
InputStream 就是字節(jié)輸入流状您,是一個(gè)抽象類(lèi)。所有繼承了 InputStream 的類(lèi)都是字節(jié)輸入流兜挨,InputStream是用來(lái)從文件中讀取基本數(shù)據(jù)類(lèi)型值的 Java API接口膏孟。主要子類(lèi)
- 文件輸入流<FileInputStream>:
- 對(duì)象輸入流<ObjectInputStream>:
- 過(guò)濾輸入流<FilterInputStream>:
- 緩存輸入流<BufferedInputStream>:
- 字段
- int MAX_SKIP_BUFFER_SIZE = 2048:用于確定 跳過(guò)時(shí)要使用的最大緩沖區(qū)大小。
- 常用方法
- int read() :從輸入流讀取下一個(gè)數(shù)據(jù)字節(jié)拌汇,讀到文件末尾時(shí)返回 -1柒桑;
- int read(byte[] b) :從輸入流中每次最多讀取b.length個(gè)字節(jié),并將讀取的數(shù)據(jù)存儲(chǔ)在緩沖區(qū)數(shù)組b中噪舀;
- int read(byte[] b, int off, int len) :將輸入流中 從偏移量off開(kāi)始的最多l(xiāng)en個(gè)數(shù)據(jù)字節(jié)讀入byte數(shù)組b中魁淳;
- long skip(long n):跳過(guò)和丟棄此輸入流中數(shù)據(jù)的 n個(gè)字節(jié)(從下標(biāo)0開(kāi)始);
- void close() :關(guān)閉此輸入流并釋放與該流關(guān)聯(lián)的所有系統(tǒng)資源与倡,finally中執(zhí)行釋放界逛。
1.2 字節(jié)輸出流<OutputStream>
- 概念
OutputStream 就是字節(jié)輸出流,是一個(gè)抽象類(lèi)纺座,所有繼承了 OutputStream 的類(lèi)都是字節(jié)輸出流息拜。OuputStream是用來(lái)將 基本數(shù)據(jù)類(lèi)型數(shù)據(jù)寫(xiě)入文件的 Java API接口。 - 主要子類(lèi)
- 文件輸出流<FileOutputStream>:
- 對(duì)象輸出流<ObjectOutputStream>:
- 過(guò)濾輸出流<FilterOutputStream>:
- 緩存流<BufferedOutputStream>:
- 打印流<PrintStream>:
- 主要方法
- void write(int b):將指定的字節(jié)內(nèi)容寫(xiě)入此輸出流,通過(guò)輸出流將字節(jié)數(shù)據(jù)寫(xiě)到文件中少欺;
- void write(byte[] b) :將 b.length個(gè)字節(jié)從指定的字節(jié)數(shù)組寫(xiě)入此輸出流喳瓣;
- void write(byte[] b, int off, int len) :將指定字節(jié)數(shù)組中 從偏移量off 開(kāi)始的 len個(gè)字節(jié)寫(xiě)入此輸出流;
- void flush() :write()寫(xiě)完后赞别,刷新此輸出流畏陕,并強(qiáng)制寫(xiě)出所有管道中緩沖的輸出字節(jié);
- void close() :關(guān)閉此輸出流并釋放與此流有關(guān)的所有系統(tǒng)資源仿滔。
1.3 字符輸入流<Reader>
概念
Reader 就是字符輸入流惠毁,是一個(gè)抽象類(lèi),所有繼承了 Reader 的類(lèi)都是字符輸入流崎页。Reader是用于讀取字符流的抽象類(lèi)仁讨,子類(lèi)必須實(shí)現(xiàn)其read(char[], int, int) 和 close()方法。同時(shí)实昨,多數(shù)子類(lèi)將重寫(xiě)其定義的一些方法洞豁,以提供更高的效率和其他功能。主要子類(lèi)
- 緩存輸入流<BufferedReader >:
- 字節(jié)轉(zhuǎn)字符輸入流<InputStreamReader >:
- 字符文件輸入流<FileReader >:
- 字段
- Object lock:用于同步 針對(duì)此流的操作的對(duì)象荒给。
- 主要方法
- Reader():無(wú)參構(gòu)造丈挟,創(chuàng)建一個(gè)新的字符輸入流對(duì)象,并同步自身志电;
- Reader(Object lock):帶參構(gòu)造曙咽,創(chuàng)建一個(gè)新的字符輸入流對(duì)象,并同步給定的對(duì)象挑辆;
- int read() :讀取單個(gè)字符例朱,如果已讀到文件末尾,則返回 -1鱼蝉;
- int read(char[] cbuf) :將輸入流讀取得到的字符數(shù)據(jù)存入char[]數(shù)組洒嗤;
- int read(char[] cbuf, int off, int len) :從數(shù)組的偏移量off開(kāi)始,將len個(gè)字符讀入數(shù)組的某一部分魁亦;
- long skip(long n):讀取某個(gè)文件時(shí)跳過(guò)n個(gè)字符渔隶,從文件下標(biāo)0開(kāi)始;
- void close() :關(guān)閉該流并釋放與此流有關(guān)的所有系統(tǒng)資源洁奈。
1.4 字符輸出流<Writer>
概念
Writer 就是字符輸出流间唉,是一個(gè)抽象類(lèi),所有繼承了 Writer 的類(lèi)都是字符輸出流利术。Writer是寫(xiě)入字符流的抽象類(lèi)呈野,子類(lèi)必須實(shí)現(xiàn)其write(char[], int, int)、flush() 和 close()方法印叁,完成數(shù)據(jù)到文件的寫(xiě)入被冒。同時(shí)商佛,多數(shù)子類(lèi)將重寫(xiě)其定義的一些方法,以提供更高的效率和其他功能姆打。主要子類(lèi)
- 緩存流<BufferedWriter>:
- 字節(jié)到字符轉(zhuǎn)換流<OutputStreamWriter>:
- 字符文件輸出流<FileWriter>:
- 打印流<PrintWriter>:
- 主要方法
- Writer append(char c) :將指定字符追加到此 writer;
- void write(int c) :往文件中寫(xiě)入單個(gè)字符肠虽,寫(xiě)入前先清空文件原內(nèi)容幔戏;
- void write(char[] cbuf) :往文件中寫(xiě)入字符數(shù)組,每次最多寫(xiě)入cbuf.length個(gè)字符税课;
- void write(char[] cbuf, int off, int len) :往字符數(shù)組的某一部分闲延,從字符數(shù)組的下標(biāo)off開(kāi)始,寫(xiě)入len個(gè)長(zhǎng)度字符到文件中韩玩;
- void write(String str) :往文件中寫(xiě)入字符串垒玲;
- void write(String str, int off, int len) :往文件中寫(xiě)入字符串的某一部分,從字符串下標(biāo)off開(kāi)始找颓,寫(xiě)入len個(gè)長(zhǎng)度字符合愈;
- void flush() :刷新此輸出流,將管道中的數(shù)據(jù)刷出寫(xiě)入到文件中击狮;
- void close() :關(guān)閉此流并釋放與此流有關(guān)的所有系統(tǒng)資源佛析,但要先執(zhí)行 flush() 刷新它。
1.5 flush()方法
flush 的含義是刷新緩沖區(qū)彪蓬,就是將緩存區(qū)中的數(shù)據(jù)寫(xiě)到磁盤(pán)上寸莫,而不再把數(shù)據(jù)放到內(nèi)存里。在執(zhí)行 os.close()時(shí)档冬,會(huì)默認(rèn)執(zhí)行 os.flush()膘茎,編寫(xiě)代碼時(shí)可以不用顯示的調(diào)用。
二酷誓、文件流
- 概念
文件流是指在程序開(kāi)發(fā)中披坏,完成對(duì)文件的讀寫(xiě)操作的流稱(chēng)為文件流。
該流用于讀取和寫(xiě)入普通文本盐数、圖像刮萌、音頻、視頻等格式文件娘扩。 - 分類(lèi)
- 文件字節(jié)輸入流<FileInputStream>
- 文件字節(jié)輸出流<FileOutputStream>
- 文件字符輸入流<FileReader >
- 文件字符輸出流<FileWriter>
- 區(qū)別
- 字節(jié)流:每次讀取一個(gè)字節(jié)着茸,使用byte[]數(shù)組存儲(chǔ)、讀寫(xiě)多個(gè)字節(jié)琐旁;可以讀取所有的形式文件(文本涮阔、視頻、音頻灰殴、圖片等)敬特;
- 字符流:每次讀取一個(gè)字符掰邢,使用char[]數(shù)組存儲(chǔ)、讀寫(xiě)多個(gè)字符伟阔;只適合于讀取普通文本文件辣之。
2.1 文件字節(jié)輸入流<FileInputStream,掌握>
- 概念
FileInputStream是從文件系統(tǒng)(硬盤(pán))中的某個(gè)文件中 獲得輸入字節(jié)皱炉。主要按照字節(jié)的方式讀取硬盤(pán)上的文件內(nèi)容怀估,每次讀取一個(gè)字節(jié)。FileInputStream 用于讀取諸如圖像數(shù)據(jù)之類(lèi)的原始字節(jié)流合搅。
<文件內(nèi)容在計(jì)算機(jī)底層都是以 二進(jìn)制的補(bǔ)碼形式存在居扒,1字節(jié) = 8位>惫谤。 - 常用方法
- FileInputStream(String name):帶參構(gòu)造方法委煤,根據(jù)指定文件路徑創(chuàng)建字節(jié)輸入流對(duì)象蹋宦;
- int read() :從輸入流讀取文件的下一個(gè)數(shù)據(jù)字節(jié),若已到達(dá)文件末尾則返回 -1赌髓;
- int read(byte[] b) :從 輸入流中每一次讀取 最多b.length個(gè)字節(jié)从藤,并將讀取的內(nèi)容存儲(chǔ)在緩沖區(qū)的byte數(shù)組中;
- int available():每一次讀取時(shí)锁蠕,剩余未讀的字節(jié)個(gè)數(shù)呛哟,結(jié)合 read(byte[] b) 方法作為byte[ available() ]數(shù)組的容量 最佳,但過(guò)大時(shí)會(huì)超出byte數(shù)組的容量匿沛;
- long skip(long n):跳過(guò)n個(gè)字節(jié)"選擇"讀取扫责,返回讀取時(shí)實(shí)際跳過(guò)的字節(jié)數(shù);
- void close() :關(guān)閉此輸入流并釋放與該流關(guān)聯(lián)的所有系統(tǒng)資源逃呼。
-
FileInputStream讀取文件圖解
FileInputStream讀取文件.png - 代碼實(shí)現(xiàn)
//創(chuàng)建文件輸入流引用
FileInputStream fis = null;
try {
//創(chuàng)建 從指定路徑讀取文件的 輸入流對(duì)象鳖孤,
fis = new FileInputStream("c:\\test.txt");
int b = 0;//存儲(chǔ)每次讀取文件返回的字節(jié)數(shù)據(jù) 個(gè)數(shù)
while ((b = fis.read()) != -1) {
//System.out.print(b);//輸出讀取到的單個(gè)字節(jié)
System.out.print((char)b);//將讀取得到的單個(gè)字節(jié) 轉(zhuǎn)換成字符輸出
}
//采用read(byte[] bytes)方法讀取時(shí),結(jié)合使用available()作為bytes數(shù)組的容量抡笼,但數(shù)據(jù)過(guò)大時(shí)不能使用
// byte[] bytes = new byte[fis.available()];
//采用字節(jié)數(shù)組存儲(chǔ)字節(jié)流讀取文件的數(shù)據(jù)
byte[] b1 = new byte[4];
int readcount = 0;//存儲(chǔ)每次讀取數(shù)組 返回的字節(jié)個(gè)數(shù)
//當(dāng)返回讀取的字節(jié)個(gè)數(shù)不為0
while ((readcount = fis.read(b1)) != -1){
//將每一次讀取byte數(shù)組中的數(shù)據(jù)轉(zhuǎn)換為字符串輸出苏揣,每次讀取幾個(gè)就輸出幾個(gè)
String s1 = new String(b1,0,readcount);
System.out.print(s1);//
}
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally { //當(dāng)輸入流為空時(shí),關(guān)閉流推姻,釋放內(nèi)存
try {
if (fis != null){
is.close();
}
}catch(IOException e) {}
}
- 注意點(diǎn)
- 常常使用 fis.read() != -1判斷是否讀取到了文件末尾平匈;
- 使用 byte數(shù)組存儲(chǔ)讀取文件的數(shù)據(jù)時(shí),想要每次讀取幾個(gè)就輸出幾個(gè)藏古,就使用一個(gè)變量temp 接收每次讀取的個(gè)數(shù)增炭;
- 采用字節(jié)輸入流讀取漢字文本文件時(shí),因?yàn)槊總€(gè)漢字占據(jù)兩個(gè)字節(jié)拧晕,而字節(jié)輸入流每次只能讀取一個(gè)字節(jié)隙姿,導(dǎo)致每個(gè)漢字的讀取分為"不完整的"兩部分,從而產(chǎn)生亂碼厂捞。
2.2 文件字節(jié)輸出流<FileOutputStream输玷,掌握>
概念
文件輸出流是 將數(shù)據(jù)寫(xiě)入文件的輸出流队丝。"寫(xiě)入文件"是否可用 或 能否被創(chuàng)建,取決于基礎(chǔ)平臺(tái)欲鹏,某些平臺(tái)一次只允許一個(gè)文件流對(duì)象打開(kāi)文件進(jìn)行寫(xiě)入机久。若所涉及的文件已經(jīng)打開(kāi),則此類(lèi)中的構(gòu)造方法將失斉夂俊(一個(gè)文件無(wú)法被兩個(gè)輸出流同時(shí)寫(xiě)入數(shù)據(jù))膘盖。特點(diǎn)
文件字節(jié)輸出流按照 字節(jié)方式寫(xiě)出文件,適用于寫(xiě)入諸如圖像數(shù)據(jù)之類(lèi)的原始字節(jié)的流尽狠。經(jīng)典案例
文件復(fù)制:首先判斷該文件是否存在。文件存在叶圃,則(采用輸入流)讀取文件袄膏,讀取后將該文件(采用輸出流)另寫(xiě)一份保存到磁盤(pán)上,完成文件的復(fù)制備份掺冠。-
文件字節(jié)輸出圖
文件字節(jié)輸出流.png 常用方法
- FileOutputStream(String name):帶參構(gòu)造沉馆,創(chuàng)建一個(gè) 向指定文件寫(xiě)入數(shù)據(jù)的 字節(jié)輸出流對(duì)象,寫(xiě)入時(shí)默認(rèn)清空文件的所有內(nèi)容再寫(xiě)入德崭;
- FileOutputStream(String name, boolean append):帶參構(gòu)造斥黑,創(chuàng)建一個(gè) 向指定文件寫(xiě)入數(shù)據(jù)的 字節(jié)輸出流對(duì)象;第二個(gè)參數(shù)為 true眉厨,表示將字節(jié)追加寫(xiě)入文件末尾處锌奴,而不是清空文件再寫(xiě)入文件開(kāi)始處;
- void write(int b):輸出流將指定的字節(jié)b寫(xiě)入文件憾股,一次寫(xiě)入一個(gè)長(zhǎng)度的字節(jié)鹿蜀;
- void write(byte[] b) :輸出流每次將最多 b.length 個(gè)字節(jié)從指定 byte 數(shù)組寫(xiě)入此文件,通常byte數(shù)組是由輸入流讀取得到的"復(fù)制內(nèi)容"服球;
- void writeBytes(byte b[], int off, int len, boolean append):輸出流將數(shù)組的一部分內(nèi)容寫(xiě)入文件茴恰,并使用append判斷是清空原文件內(nèi)容寫(xiě)入,或是在原文件的末尾追加寫(xiě)入斩熊;
- void close() :關(guān)閉此輸出流 并釋放與此流有關(guān)的所有系統(tǒng)資源往枣。
- 代碼實(shí)現(xiàn)
//創(chuàng)建文件輸出流引用
FileOutputStream fos = null;
try {
//創(chuàng)建 指定路徑寫(xiě)出文件的 輸出流文件對(duì)象,若文件不存在則在該路徑新建文件粉渠,若文件存在則清空文件的內(nèi)容再寫(xiě)入
fos = new FileOutputStream("d:\\test.txt.bak");
//創(chuàng)建一個(gè)輸出流對(duì)象分冈,寫(xiě)入時(shí)不清空已存在文件的內(nèi)容,而是在文件末尾追加寫(xiě)入的內(nèi)容
// fos = new FileOutputStream("d:\\test.txt.bak"霸株,true);
//寫(xiě)入單個(gè)字符
fos.write(1);
//寫(xiě)入字符串
fos.write("Hello world!");
//寫(xiě)入char數(shù)組
char[] ac = {'我','是','中','國(guó)','人'};
fos.write(ac);
//寫(xiě)入完成丈秩,刷新管道
fos.flush();
System.out.println("文件復(fù)制完畢!");
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally {
// 分開(kāi)try淳衙,不要一起try蘑秽, 一起try時(shí)饺著,其中一個(gè)出現(xiàn)異常,可能會(huì)影響到另一個(gè)流的關(guān)閉肠牲。
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
- 注意點(diǎn)
- 對(duì)于FileOutPutStream要寫(xiě)入的文件幼衰,若文件在對(duì)象創(chuàng)建前已存在,直接對(duì)已存在文件進(jìn)行寫(xiě)入缀雳;若文件不存在渡嚣,則會(huì)在指定路徑下新建文件再寫(xiě)入;
- FileOutPutStream對(duì)象的創(chuàng)建:調(diào)用構(gòu)造器時(shí)肥印,注意區(qū)分單參構(gòu)造和雙參構(gòu)造识椰,單參構(gòu)造會(huì)清空寫(xiě)入文件的所有內(nèi)容再將新數(shù)據(jù)寫(xiě)進(jìn);雙參構(gòu)造append若是true時(shí)深碱,則不會(huì)清空文件內(nèi)容腹鹉,而在文件末尾追加寫(xiě)入的數(shù)據(jù)。
2.3 文件字符輸入流<FileReader >
- 概念
FileReader是用來(lái)讀取字符文件的便捷類(lèi)敷硅。主要按照 字符(雙字節(jié))的方式讀取文件內(nèi)容功咒,即每次讀取兩個(gè)字節(jié)。<底層使用兩個(gè)字節(jié)位00110101 10111001>绞蹦。 -
文件字符輸入流圖
文件字符輸入流.png - 常用方法
- FileReader(String fileName):帶參構(gòu)造力奋,在指定路徑下創(chuàng)建一個(gè)字符輸入流對(duì)象,讀取文件數(shù)據(jù)(底層調(diào)用FileInputStream對(duì)象的創(chuàng)建方式)幽七;
- int read() :從輸入流讀取單個(gè)字符景殷,以int類(lèi)型變量接收讀取的字符;
- int read(char[] c) :從輸入流 將字符讀入數(shù)組澡屡,一次讀入最多c.length個(gè)長(zhǎng)度字符滨彻;
- void close() :關(guān)閉該流并釋放與此流有關(guān)的所有系統(tǒng)資源。
- 代碼實(shí)現(xiàn)
//創(chuàng)建字符輸入流引用
FileReader fileReader = null;
try {
//創(chuàng)建實(shí)際的字符輸入流對(duì)象
fileReader = new FileReader("");
//讀取單個(gè)字符
fileReader.read();
//用于存儲(chǔ) 每次讀取返回的字節(jié)個(gè)數(shù)
int readcount = 0;
char[] ac = new char[8];
//讀取數(shù)組
fileReader.read(ac);
while ((readcount = fileReader.read(ac)) !=-1){
//讀取數(shù)組的一部分
fileReader.read(ac, 0, readcount);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
2.4 文件字符輸出流<FileWriter>
- 概念
FileWriter是用來(lái)寫(xiě)入字符文件的便捷類(lèi)挪蹭,每一次輸出按照字符方式(雙字節(jié))寫(xiě)出文件亭饵。 -
文件字符輸出流圖
文件字符輸出流.png - 常用方法
- FileWriter(String fileName):帶參構(gòu)造,創(chuàng)建一個(gè) 向指定名稱(chēng)的文件中寫(xiě)入數(shù)據(jù)的 字符輸出流對(duì)象梁厉;
- FileWriter(String fileName, boolean append):帶參構(gòu)造辜羊,創(chuàng)建一個(gè) 向指定名稱(chēng)的文件中寫(xiě)入數(shù)據(jù)的 字符輸出流對(duì)象;第二個(gè)參數(shù)為 true词顾,表示將字節(jié)寫(xiě)入文件末尾處八秃,而不是寫(xiě)入文件開(kāi)始處;
- void flush() :刷新此輸出流肉盹,將可能殘留在管道中的數(shù)據(jù)刷出到文件中(一般在關(guān)閉流之前刷新)昔驱;
- void close() :關(guān)閉此流并釋放與此流有關(guān)的所有系統(tǒng)資源,但要先執(zhí)行 flush() 刷新上忍;
- void write(int c) :在輸出流中寫(xiě)入單個(gè)字符骤肛;
- void write(String str) :在輸出流中寫(xiě)入字符串纳本。
- 代碼實(shí)現(xiàn)
//創(chuàng)建一個(gè)文件字符輸出流引用
FileWriter fileWriter = null;
try {
//創(chuàng)建實(shí)際的字符輸出流對(duì)象
fileWriter = new FileWriter("");
//創(chuàng)建實(shí)際的字符輸出流對(duì)象,true表示在輸出文件后面進(jìn)行append追加內(nèi)容
//fileWriter = new FileWriter("",true);
//寫(xiě)入單個(gè)字符
fileWriter.write(1);
//寫(xiě)入字符串
fileWriter.write("Hello world!");
//寫(xiě)入char數(shù)組
char[] ac = {'我','是','中','國(guó)','人'};
fileWriter.write(ac);
//寫(xiě)入完成腋颠,刷新管道
fileWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileWriter != null){
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
三繁成、緩沖流<BufferedStream>
概念
緩沖流主要是通過(guò)減少物理讀取次數(shù)(程序從硬盤(pán)中讀取文件的次數(shù))的流,通過(guò)將硬盤(pán)數(shù)據(jù)讀取到一個(gè)緩沖管道中淑玫,下一次直接從緩沖管道中讀取巾腕,減少內(nèi)存與硬盤(pán)的交流次數(shù)。緩沖流是為了提高效率而存在的絮蒿。分類(lèi)
- 緩沖字節(jié)輸入流<BufferedInputStream>
- 緩沖字節(jié)輸出流<BufferedOutputStream>
- 緩沖字符輸入流<BufferedReader>
- 緩沖字符輸出流<BufferedWriter>
- 特點(diǎn)
- 構(gòu)造方法節(jié)點(diǎn)流:緩沖流的構(gòu)造方法中需要一個(gè)節(jié)點(diǎn)流作為第一參數(shù)尊搬,不像文件流直接使用文件路徑或文件創(chuàng)建對(duì)象,緩沖流必須使用父類(lèi)的字節(jié)輸入/輸出流土涝、字符輸入輸出流的對(duì)象作為第一參數(shù)佛寿;
- 流自帶緩沖區(qū):緩沖流中自帶有數(shù)據(jù)緩沖區(qū),無(wú)需像文件流一樣創(chuàng)建自定義byte[]數(shù)組或char[]數(shù)組存儲(chǔ) 字節(jié)/字符輸入流讀取文件的數(shù)據(jù)回铛;
- 節(jié)點(diǎn)流狗准、包裝流與處理流
- 節(jié)點(diǎn)流:指的是在一個(gè)流的構(gòu)造方法內(nèi)還需要另外一個(gè)流作為參數(shù)克锣,而作為參數(shù)的流就稱(chēng)為節(jié)點(diǎn)流茵肃,在關(guān)閉流釋放資源時(shí),只需關(guān)閉外部流袭祟,不需要關(guān)閉節(jié)點(diǎn)流(外部流的close()底層自動(dòng)關(guān)閉節(jié)點(diǎn)流)验残;
- 包裝流/ 處理流:指的是使用節(jié)點(diǎn)流作為其構(gòu)造方法參數(shù)的流,實(shí)際上對(duì)文件進(jìn)行操作處理的流巾乳。
3.1 緩沖字節(jié)輸入流<BufferedInputStream>
- 概念
BufferedInputStream為另一個(gè)輸入流InputStream擴(kuò)展功能您没,添加了緩沖輸入、支持 mark() 和 reset()方法的能力胆绊。在創(chuàng)建 BufferedInputStream 時(shí)氨鹏,會(huì)創(chuàng)建一個(gè)內(nèi)部緩沖區(qū)數(shù)組,在讀取或跳過(guò)流中的字節(jié)時(shí)压状,可根據(jù)需要從包含的輸入流再次填充該內(nèi)部緩沖區(qū)仆抵,一次填充多個(gè)字節(jié)。 - 特點(diǎn)
- mark()方法 記錄輸入流中的某個(gè)點(diǎn)种冬;
- reset()方法使得在 從包含的輸入流中獲取新字節(jié) 之前镣丑,再次讀取自最后一次標(biāo)記后讀取的所有字節(jié)。
- 字段
- int DEFAULT_BUFFER_SIZE = 8192:默認(rèn)字符緩沖區(qū)的大杏榱健莺匠;
- int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8:該流支持的最大緩沖區(qū)大小十兢;
- volatile byte buf[]:存儲(chǔ) 從字節(jié)輸入流中讀取的數(shù)據(jù) 的內(nèi)部緩沖數(shù)組趣竣;
- int count:比緩沖區(qū)中最后一個(gè)有效字節(jié)的索引 大1的索引摇庙;
- int pos:緩沖區(qū)中的當(dāng)前位置position;
- int markpos = -1:最后一次調(diào)用mark()方法時(shí) 緩沖區(qū)的位置期贫。
- 常用方法
- BufferedInputStream(InputStream in):帶參構(gòu)造跟匆,創(chuàng)建一個(gè)默認(rèn)緩沖區(qū)大小的字節(jié)緩存輸入流對(duì)象,底層使用輸入流 in通砍;
- BufferedInputStream(InputStream in, int size):帶參構(gòu)造玛臂,創(chuàng)建一個(gè)size長(zhǎng)度的指定緩沖區(qū)大小的 字節(jié)緩存輸入流對(duì)象,底層使用輸入流 in封孙;
- int read():從輸入流中讀取數(shù)據(jù)的下一個(gè)字節(jié)迹冤;
- int read(byte b[], int off, int len):將輸入流中的 len個(gè)數(shù)據(jù)字節(jié)讀入byte 數(shù)組中,從數(shù)組的下標(biāo)off開(kāi)始存儲(chǔ)虎忌;
- long skip(long n):跳過(guò)和丟棄此輸入流中數(shù)據(jù)的 n個(gè)字節(jié)泡徙;
- void mark(int readlimit):在此輸入流中標(biāo)記當(dāng)前的位置;
- void close():關(guān)閉此輸入流并釋放與該流關(guān)聯(lián)的所有系統(tǒng)資源膜蠢。
//創(chuàng)建字節(jié)輸入流對(duì)象--緩沖流中的節(jié)點(diǎn)流
FileInputStream fis = new FileInputStream("");
//創(chuàng)建緩沖字節(jié)輸出流對(duì)象--參數(shù)為節(jié)點(diǎn)流
BufferedInputStream bis = new BufferedInputStream(fis);
//創(chuàng)建緩沖字節(jié)輸出流對(duì)象--參數(shù)為節(jié)點(diǎn)流堪藐,且緩沖流本身自帶的緩沖區(qū)大小為128字節(jié)
BufferedInputStream biss = new BufferedInputStream(fis,128);
//查看緩沖流本身緩沖區(qū)的大小
bis.available();
//讀取單個(gè)字節(jié)
bis.read();
byte[] b1 = new byte[32];
//讀取字節(jié)數(shù)組
bis.read(b1);
int readcount = 0;
//讀取字節(jié)數(shù)組的一部分
bis.read(b1,0,readcount);
//關(guān)閉流資源,釋放內(nèi)存
bis.close();
3.2 緩沖字節(jié)輸出流<BufferedOutputStream>
- 概念
BufferedOutputStream類(lèi)是實(shí)現(xiàn)緩沖的輸出流挑围。通過(guò)設(shè)置這種輸出流礁竞,應(yīng)用程序可以將各個(gè)字節(jié)寫(xiě)入底層輸出流InputStream中,不必針對(duì)每次字節(jié)寫(xiě)入都調(diào)用底層系統(tǒng)杉辙。 - 字段
- byte buf[]:存儲(chǔ)數(shù)據(jù)的內(nèi)部緩沖區(qū)模捂;
- int count:緩沖區(qū)中的有效字節(jié)數(shù)。
- 常用方法
- BufferedOutputStream(OutputStream out):帶參構(gòu)造蜘矢,創(chuàng)建一個(gè)默認(rèn)緩沖區(qū)大小為8192的 字節(jié)緩存輸出流對(duì)象狂男,底層使用輸出流 out;
- BufferedOutputStream(OutputStream out, int size):帶參構(gòu)造品腹,創(chuàng)建一個(gè)指定size長(zhǎng)度的緩沖區(qū)大小的 字節(jié)緩存輸入流對(duì)象岖食,底層使用輸出流 out;
- void flushBuffer():刷新此字符緩沖區(qū)舞吭;
- void write(int b):將字符數(shù)據(jù)b寫(xiě)入緩沖輸出流泡垃;
- void write(byte b[], int off, int len):將字符數(shù)組中指定len個(gè)長(zhǎng)度的數(shù)據(jù)寫(xiě)入緩沖輸出流,從數(shù)組中的下標(biāo)off開(kāi)始镣典;
- void flush():刷新此字符緩沖輸出流兔毙,將管道中的數(shù)據(jù)刷新到文件中。
//創(chuàng)建字節(jié)輸出流對(duì)象--作為緩沖流的節(jié)點(diǎn)流
FileOutputStream fos = new FileOutputStream("");
//創(chuàng)建緩沖字節(jié)流輸出對(duì)象
BufferedOutputStream bos = new BufferedOutputStream(fos);
//創(chuàng)建緩沖字節(jié)流輸出對(duì)象兄春,且緩沖流自身的緩沖區(qū)大小為28字節(jié)
//BufferedOutputStream boss = new BufferedOutputStream(fos,128);
//寫(xiě)出單個(gè)字節(jié)
bos.write(12);
//寫(xiě)出字節(jié)數(shù)組
byte[] b1 = new byte[128];
bos.write(b1);
int writecount = 0;
//寫(xiě)出字節(jié)數(shù)組的一部分
bos.write(b1,0,writecount);
//刷新緩沖流
bos.flush();
//關(guān)閉緩沖流
bos.close();
3.3 緩沖字符輸入流<BufferedReader>
- 概念
BufferedReader是從字符輸入流中讀取文本(不是直接從文件中)澎剥,緩沖各個(gè)字符,從而實(shí)現(xiàn)字符、數(shù)組和行的高效讀取哑姚。 BufferedReader可以指定緩沖區(qū)的大小祭饭,或者使用默認(rèn)大小。大多數(shù)情況下叙量,默認(rèn)值足夠大倡蝙。 - 特點(diǎn)
緩沖指定文件的輸入。如果沒(méi)有緩沖绞佩,每次調(diào)用 read()或 readLine()方法都會(huì)導(dǎo)致從文件中讀取字節(jié)寺鸥,再將其轉(zhuǎn)換為字符后返回,是極其低效的品山。 - 字段
- Reader in:字符輸入流對(duì)象(節(jié)點(diǎn)流)胆建,用于BufferedReader構(gòu)造方法中的第一參數(shù);
- char cb[]:流本身自帶用于存儲(chǔ) 從字符輸入流中讀取的數(shù)據(jù)的字符數(shù)組肘交;
- int defaultCharBufferSize = 8192:默認(rèn)自身緩沖區(qū)的大小為8192字節(jié)笆载。
- 常用方法
- BufferedReader(Reader in):創(chuàng)建一個(gè)默認(rèn)大小輸入緩沖區(qū)的緩沖字符輸入流,需要一個(gè)節(jié)點(diǎn)流Reader作為對(duì)象涯呻;
- BufferedReader(Reader in, int sz):帶參構(gòu)造凉驻,創(chuàng)建一個(gè)指定sz大小輸入緩沖區(qū)的緩沖字符輸入流;
- int read():從字符輸入流中讀取單個(gè)字符复罐;
- read(char cbuf[], int off, int len):將字符讀入到數(shù)組中的某一部分涝登;
- String readLine(): 從字符輸入流中直接讀取一個(gè)文本行,遇到指定字符時(shí)某行終止(換行 '\n'市栗、回車(chē) '\r' 缀拭、回車(chē)后跟著的換行)咳短,該方法本身讀取不到換行符填帽;
- long skip(long n):從字符輸出流中讀取時(shí),跳過(guò)指定n個(gè)字符咙好,從下標(biāo)0開(kāi)始篡腌;
- void close():關(guān)閉該緩沖流,釋放內(nèi)存勾效。
3.4 緩沖字符輸出流<BufferedWriter>
- 概念
BufferedWriter將文本寫(xiě)入字符輸出流嘹悼,緩沖各個(gè)字符,從而提供單個(gè)字符层宫、數(shù)組和字符串的高效寫(xiě)入杨伙。可以指定緩沖區(qū)的大小萌腿,或接受默認(rèn)的大小限匣。大多數(shù)情況下,默認(rèn)值足夠大毁菱。 - 特點(diǎn)
將緩沖 PrintWriter對(duì)文件的輸出米死。如果沒(méi)有緩沖锌历,每次調(diào)用 print()方法都會(huì)將字符轉(zhuǎn)換為字節(jié),再寫(xiě)入到文件峦筒,是極其低效的究西。 - 字段
- Writer out:字符輸出對(duì)象,用于BufferedWriter構(gòu)造方法中物喷;
- char cb[]:用于存儲(chǔ) 從字符輸入流中讀取的數(shù)據(jù)的 字符數(shù)組卤材;
- int defaultCharBufferSize = 8192:默認(rèn)緩沖區(qū)大小8192字節(jié)。
- 常用方法
- BufferedWriter(Writer out):帶參構(gòu)造峦失,創(chuàng)建一個(gè)使用默認(rèn)大小輸出緩沖區(qū)的緩沖字符輸出流商膊;
- BufferedWriter(Writer out, int sz):帶參構(gòu)造,創(chuàng)建一個(gè)使用給定大小輸出緩沖區(qū)的新緩沖字符輸出流宠进;
- void ensureOpen():確認(rèn)該輸出流打開(kāi)(正在使用可輸出)晕拆;
- void write(int c):寫(xiě)入單個(gè)字符, c-是指定要寫(xiě)入字符材蹬;
- void write(char cbuf[], int off, int len):將字符數(shù)組中的某一部分寫(xiě)入流实幕,從字符數(shù)組的下標(biāo)off開(kāi)始,寫(xiě)入len個(gè)長(zhǎng)度字符堤器;
- void write(String s, int off, int len):將字符串的某一部分寫(xiě)入流昆庇,從字符串的下標(biāo)off開(kāi)始,寫(xiě)入len個(gè)長(zhǎng)度字符闸溃;
- void newLine():往流中寫(xiě)入一個(gè)行分隔符整吆;
- void flush():刷新該流的緩沖,將管道中緩沖的數(shù)據(jù)刷新到文件中辉川;
- void flushBuffer():刷新緩沖數(shù)據(jù)表蝙;
- void close():關(guān)閉此流,關(guān)閉前要先使用flush()刷新管道中的緩沖數(shù)據(jù)乓旗。
四府蛇、轉(zhuǎn)換流
- 概念
轉(zhuǎn)換流就是將一種流的方法轉(zhuǎn)換成另一種流的方式。通常是字節(jié)流轉(zhuǎn)字符流(對(duì)比基本數(shù)據(jù)類(lèi)型的轉(zhuǎn)換屿愚,小轉(zhuǎn)大可以自動(dòng)轉(zhuǎn)汇跨,大轉(zhuǎn)小會(huì)損失精度,單字節(jié)容納不下雙字節(jié))妆距。 - 主要子類(lèi)
- 字節(jié)轉(zhuǎn)字符輸入<InputStreamReader>:
- 字節(jié)轉(zhuǎn)字符輸出<OutputStreamWriter>:
- 用途
作為一個(gè)"包裝類(lèi)"穷遂,將字節(jié)流轉(zhuǎn)換為字符流,結(jié)合緩沖流的構(gòu)造方法中的節(jié)點(diǎn)流一起使用更合適娱据。
4.1 字節(jié)轉(zhuǎn)字符輸入<InputStreamReader>
- 概念
InputStreamReader就是將字節(jié)流輸入流轉(zhuǎn)換成字符輸入流蚪黑,由字面理解就是InputStream → Reader。它使用指定的字符編碼讀取字節(jié) 并將其解碼為字符,使用的字符集可以由名稱(chēng)指定祠锣、顯式給定酷窥,或者接受平臺(tái)默認(rèn)的字符集。 - 特點(diǎn)
- 字段
- StreamDecoder sd:流解碼器對(duì)象伴网,用于處理字節(jié)轉(zhuǎn)字符期間的編碼和解碼問(wèn)題蓬推。
- 常用方法
- InputStreamReader(InputStream in):帶參構(gòu)造,創(chuàng)建一個(gè)使用默認(rèn)字符集的 字節(jié)轉(zhuǎn)字符輸入對(duì)象澡腾,底層使用字節(jié)輸入流對(duì)象in沸伏;
- InputStreamReader(InputStream in, String charsetName):帶參構(gòu)造,創(chuàng)建使用指定字符集的 字節(jié)轉(zhuǎn)字符輸入對(duì)象动分;
- InputStreamReader(InputStream in, Charset cs):帶參構(gòu)造毅糟,創(chuàng)建使用給定字符集的 字節(jié)轉(zhuǎn)字符輸入對(duì)象;
- InputStreamReader(InputStream in, CharsetDecoder dec):帶參構(gòu)造澜公,創(chuàng)建使用給定字符集解碼器的 字節(jié)轉(zhuǎn)字符輸入對(duì)象姆另;
- boolean ready():判斷此流是否已經(jīng)準(zhǔn)備好用于讀取,讀取前判斷再使用坟乾;
- int read():讀取單個(gè)字符迹辐,如果已到達(dá)流的末尾,則返回 -1 甚侣;
- int read(char cbuf[], int offset, int length):將字符讀入到數(shù)組中的某一部分明吩,從數(shù)組下標(biāo)offset開(kāi)始存儲(chǔ),讀取length個(gè)長(zhǎng)度殷费;
- void close():關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源印荔。
- 代碼示例
//創(chuàng)建字符輸入流
FileReader fr = new FileReader("");
//創(chuàng)建字節(jié)緩沖流--內(nèi)部參數(shù)為字符流對(duì)象
BufferedReader br1 = new BufferedReader(fr);
//創(chuàng)建字節(jié)輸入流
FileInputStream fio = new FileInputStream("");
//將字節(jié)輸入流fio 轉(zhuǎn)成 字符輸入流
InputStreamReader isr = new InputStreamReader(fio);
//創(chuàng)建字節(jié)緩沖流--內(nèi)部參數(shù)為字符流對(duì)象
BufferedReader br = new BufferedReader(isr);
//合并-字節(jié)流--字節(jié)轉(zhuǎn)字符流--字符緩沖流(字符流對(duì)象參數(shù))
BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream("")));
bfr = new BufferedReader(new InputStreamReader(System.in));
String s = null;
while ((s=br.readLine()) != null) {
System.out.println(s);
//讀取到字母 q時(shí)退出循環(huán)
if ("q".equals(s)) {
break;
}
}
if (bfr != null) {
bfr.close();
}
4.2 字節(jié)轉(zhuǎn)字符輸出<OutputStreamWriter>
- 概念
OutputStreamWriter就是將字節(jié)流輸出流轉(zhuǎn)換成字符輸出流,由字面理解就是OutputStream → Writer详羡。它使用指定的字符編碼將 要寫(xiě)入流中的字符編碼成字節(jié)仍律,使用的字符集可以由名稱(chēng)指定、顯式給定殷绍,否則接受平臺(tái)默認(rèn)的字符集染苛。 - 特點(diǎn)
- 字段
- StreamDecoder sd:流解碼器對(duì)象鹊漠,用于處理字節(jié)轉(zhuǎn)字符期間的編碼和解碼問(wèn)題主到。
- 常用方法
- OutputStreamWriter(OutputStream out):帶參構(gòu)造,創(chuàng)建使用默認(rèn)字符編碼的 字節(jié)轉(zhuǎn)字符輸出對(duì)象躯概;
- OutputStreamWriter(OutputStream out, String charsetName):帶參構(gòu)造登钥,創(chuàng)建使用指定字符集的 字節(jié)轉(zhuǎn)字符輸出對(duì)象;
- OutputStreamWriter(OutputStream out, Charset cs):帶參構(gòu)造娶靡,
創(chuàng)建使用給定字符集的 字節(jié)轉(zhuǎn)字符輸出對(duì)象牧牢; - OutputStreamWriter(OutputStream out, CharsetEncoder enc):帶參構(gòu)造, 創(chuàng)建使用給定字符集編碼器的 字節(jié)轉(zhuǎn)字符輸出對(duì)象;
- write(int c):寫(xiě)入單個(gè)字符塔鳍;
- write(char cbuf[], int off, int len):將字符數(shù)組中的某一部分寫(xiě)入流伯铣,從數(shù)組的下標(biāo)off開(kāi)始,寫(xiě)入len個(gè)長(zhǎng)度轮纫;
- void write(String str, int off, int len):將字符串中的某一部分寫(xiě)入流腔寡,從字符串的下標(biāo)off開(kāi)始,寫(xiě)入len個(gè)長(zhǎng)度掌唾;
- void flushBuffer():刷新此流緩沖區(qū)放前;
- void flush():刷新該流的緩沖,將管道中緩沖的數(shù)據(jù)全都寫(xiě)入文件糯彬;
- void close():關(guān)閉此流凭语,但要先f(wàn)lush()刷新它。
//創(chuàng)建字節(jié)輸出流對(duì)象
FileOutputStream fos = new FileOutputStream("");
//將字節(jié)輸出流--轉(zhuǎn)換--字符輸出流
OutputStreamWriter osw = new OutputStreamWriter(fos);
//創(chuàng)建字節(jié)輸出流對(duì)象
FileOutputStream fous = new FileOutputStream("");
//將字節(jié)輸出流--轉(zhuǎn)換--字符輸出流
OutputStreamWriter os = new OutputStreamWriter(fous);
//將字符輸出流--轉(zhuǎn)換--緩沖字符輸出流
BufferedWriter bw = new BufferedWriter(os);
//合并-字節(jié)輸出流--字符輸出流--緩沖字符輸出流()
BufferedWriter buw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("")));
buw.flush();
五撩扒、打印流
- 概念
打印流即從程序到內(nèi)存輸出的流似扔,由java程序向控制臺(tái)打印輸出,即完成對(duì)屏幕打印的重定向。 - 特點(diǎn)
System.out 就是打印輸出澡绩,默認(rèn)輸出到控制臺(tái)鳍侣。而打印流 PrintStream可以重定向輸出到文件,System.out.println不再輸出到屏幕辆脸,而是輸出到指定文件。 - 分類(lèi)
- 打印字節(jié)流<PrintStream>
- 打印字符流<PrintWriter>
- 輸出重定向原理
System.out默認(rèn)是PrintStream向控制臺(tái)輸出螃诅;
PrintStream 構(gòu)造時(shí)啡氢,使用指定輸出路徑的輸出流對(duì)象作為參數(shù),導(dǎo)致PrintStream的輸出不再默認(rèn)术裸,而是向指定輸出路徑輸出倘是,從而完成輸出重定向。但前提也需要System.setOut才可以修改輸出方向袭艺。
- System.setOut(new PrintStream(new OutPutStream("指定路徑")))搀崭;
5.1 打印字節(jié)流<PrintStream,掌握>
- 概念
PrintStream構(gòu)造器底層需要一個(gè)輸出流作為參數(shù)(節(jié)點(diǎn)流)猾编,因此是其他輸出流的擴(kuò)展瘤睹,為其他輸出流添加更多功能。PrintStream默認(rèn)完成由java程序向控制臺(tái)打印輸出答倡,即完成對(duì)屏幕打印的重定向轰传。 - 特點(diǎn)
- PrintStream永遠(yuǎn)不會(huì)拋出 IOException;
- PrintStream在寫(xiě)入 byte數(shù)組之后自動(dòng)調(diào)用 flush()方法完成刷新瘪撇;
- 調(diào)用println()方法获茬,表示寫(xiě)入一個(gè)換行符或字節(jié) ('\n')港庄;
- PrintStream不需要close()關(guān)閉;
- 特點(diǎn)
System.out就是 PrintStream恕曲,System.out默認(rèn)輸出到控制臺(tái)鹏氧。
而當(dāng)打印流PrintStream使用 指定路徑的輸出流作為節(jié)點(diǎn)流參數(shù) 來(lái)構(gòu)造時(shí),可以重定向輸出到文件佩谣,System.out.println不再輸出到屏幕度帮,而是輸出到指定文件。 - 字段
- boolean autoFlush:自動(dòng)刷新標(biāo)志稿存;
- BufferedWriter textOut:字符輸出對(duì)象笨篷;
- OutputStreamWriter charOut字節(jié)轉(zhuǎn)字符輸出對(duì)象;
- Formatter formatter:格式化程序瓣履,對(duì)輸出流中的數(shù)據(jù)格式化率翅;
- 常用方法
- void flush():刷新該流的緩沖,通過(guò)將所有緩沖的輸出字節(jié)寫(xiě)入到底層輸出流袖迎;
- void close():關(guān)閉流冕臭,通過(guò)刷新流然后關(guān)閉底層輸出流完成此操作;
- void write(int b):將指定的字節(jié)b寫(xiě)入此流燕锥,如果字節(jié)為新行 且啟用了自動(dòng)刷新辜贵,則調(diào)用 flush 方法;
- void write(byte[] buf,int off, int len):將byte 數(shù)組的 len長(zhǎng)度個(gè)字節(jié)從指定下標(biāo) off開(kāi)始寫(xiě)入此流归形。如果啟用自動(dòng)刷新托慨,則調(diào)用 flush 方法;
- void print(Object obj):打印數(shù)據(jù)暇榴,按照平臺(tái)的默認(rèn)字符編碼將 String.valueOf(obj)生成的字符串轉(zhuǎn)換為字節(jié)厚棵,并完全以write(int)方法的方式寫(xiě)入這些字節(jié);
- void println():通過(guò)寫(xiě)入行分隔符字符串終止當(dāng)前行蔼紧,行分隔符字符串由系統(tǒng)屬性line.separator 定義婆硬,不一定是單個(gè)換行符 '\n';
- PrintStream format(String format, Object args):使用指定格式字符串和參數(shù) 將格式化字符串寫(xiě)入此輸出流中奸例;
- PrintStream append(CharSequence csq):將指定字符序列csq添加到此輸出流彬犯;
- PrintStream append(char c):將指定字符c添加到此輸出流。
- 代碼示例
//創(chuàng)建字節(jié)輸出流引用
FileOutputStream os = null;
try {
System.out.println("asdfkjfd;lldffdfdrerere");//未改變輸出方向查吊,默認(rèn)向控制臺(tái)輸出
//創(chuàng)建具體的輸出流對(duì)象
os = new FileOutputStream("c:/console.txt");
//創(chuàng)建標(biāo)準(zhǔn)輸出流對(duì)象--采用節(jié)點(diǎn)流參數(shù)谐区,將指定文件輸出的方向
PrintStream ps = new PrintStream(os);
//PrintStream ps = System.out;
System.setOut(ps);//改變輸出方向
//System.setOut(new PrintStream(os));//合并--改變輸出方向
System.out.println("asdfkjfd;lldffdfdrerere");//向指定輸出流的文件console.txt輸出
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally { //關(guān)閉流資源菩貌,釋放內(nèi)存
try {
if (os != null) {
os.close();
}
}catch(IOException e) {}
}
5.2 打印字符流<PrintWriter>
- 概念
打印輸入流卢佣,相當(dāng)于System.in,完成 接收屏幕輸入箭阶。 - 特點(diǎn)
- 字段
-Writer out:字符輸出流對(duì)象虚茶,構(gòu)造器時(shí)使用;
- boolean autoFlush:自動(dòng)刷新標(biāo)志仇参;
- Formatter formatter:格式化對(duì)象嘹叫,對(duì)輸出流中的數(shù)據(jù)格式化;
- PrintStream psOut = null:字節(jié)打印流對(duì)象诈乒;
- String lineSeparator:行分隔符罩扇,用于print()方法中進(jìn)行行分隔的標(biāo)志;
- 常用方法
- PrintWriter (Writer out):帶參構(gòu)造怕磨,創(chuàng)建一個(gè)不帶自動(dòng)行刷新的字符打印流對(duì)象喂饥,底層調(diào)用字節(jié)輸出流對(duì)象;
- void flush():刷新該流的緩沖肠鲫,底層重寫(xiě)了Flushable接口和Writer類(lèi)的方法员帮;
- void close():關(guān)閉該流并釋放與之關(guān)聯(lián)的所有系統(tǒng)資源;
- void write(int c):寫(xiě)入單個(gè)字符c导饲;
- void write(char buf[], int off, int len):寫(xiě)入字符數(shù)組的某一部分捞高,從數(shù)組的下標(biāo)off開(kāi)始,寫(xiě)入len個(gè)長(zhǎng)度渣锦;
- void write(char buf[]):寫(xiě)入字符數(shù)組硝岗,此方法不能從 Writer類(lèi)繼承,因?yàn)樗仨毴∠?I/O 異常袋毙;
- void write(String s, int off, int len):寫(xiě)入字符串的某一部分型檀;
- void newLine():往流中寫(xiě)入一個(gè)行分隔符;
- void print(Object obj):打印數(shù)據(jù)听盖,按照平臺(tái)的默認(rèn)字符編碼將 String.valueOf(obj)生成的字符串轉(zhuǎn)換為字節(jié)贱除,并完全以write(int)方法的方式寫(xiě)入這些字節(jié);
- void println():通過(guò)寫(xiě)入行分隔符字符串終止當(dāng)前行媳溺,底層調(diào)用newLine()方法月幌;
- PrintWriter append(CharSequence csq):將指定字符序列csq添加到此輸出流;
- PrintWriter append(char c):將指定字符c添加到此輸出流悬蔽。
六扯躺、對(duì)象流<掌握>
- 概念
對(duì)象流是可以將 Java對(duì)象 轉(zhuǎn)換成二進(jìn)制進(jìn)行文件操作的流,通常對(duì)象流的輸入和輸出是以字節(jié)單位進(jìn)行的蝎困。 - 分類(lèi)
- 對(duì)象字節(jié)輸入流<ObjectInputStream>
- 對(duì)象字節(jié)輸出流<ObjectOutputStream>
- 常用方法
- writeObject(Object obj):向硬盤(pán)下的指定文件打印輸出該obj對(duì)象录语;
- readObject():從硬盤(pán)指定的文件中讀取出對(duì)象到內(nèi)存中。
6.1 對(duì)象字節(jié)輸入流<ObjectInputStream禾乘,掌握>
- 概念
ObjectInputStream類(lèi)是對(duì) 使用了 ObjectOutputStream類(lèi)寫(xiě)入的基本數(shù)據(jù)和對(duì)象進(jìn)行反序列化的對(duì)象輸入流澎埠,從磁盤(pán)中將對(duì)象反序列化到內(nèi)存中。 - 特點(diǎn)
- 字段
- 常用方法
- 代碼示例
//創(chuàng)建文件輸入流引用
FileInputStream fis = null;
//創(chuàng)建對(duì)象輸入流引用
ObjectInputStream ois = null;
//創(chuàng)建實(shí)際的文件輸入流對(duì)象--作為節(jié)點(diǎn)流參數(shù)
fis = new FileInputStream("students");
//創(chuàng)建實(shí)際的對(duì)象輸入流對(duì)象--完成反序列化的流
ois = new ObjectInputStream(fis);
//將文件中的對(duì)象反序列化到內(nèi)存中--返回的是Object類(lèi)型對(duì)象
Object o = ois.readObject();
//將反序列化的對(duì)象進(jìn)行類(lèi)型強(qiáng)轉(zhuǎn)
Student st = (Student)o;
//獲取反序列對(duì)象的各個(gè)屬性
System.out.println(st.getName());
System.out.println(st.getAge());
if (ois != null){
ois.close();
}
if (fis != null){
fis.close();
}
}
6.2 對(duì)象字節(jié)輸出流<ObjectOutputStream始藕,掌握>
- 概念
ObjectOutputStream是一個(gè)用于將java對(duì)象分段寫(xiě)入(序列化)到硬盤(pán)中的對(duì)象輸出流蒲稳。 - 特點(diǎn)
- static class Caches:靜態(tài)內(nèi)部類(lèi)--緩存氮趋,使用HashMap存儲(chǔ)數(shù)據(jù),使用ReferenceQueue參考隊(duì)列存儲(chǔ)消息江耀。
- 字段
- 常用方法
- 代碼示例
//創(chuàng)建需要進(jìn)行序列化的java對(duì)象
Student stu = new Student("zhangsan",23);
//創(chuàng)建文件輸出流引用--作為節(jié)點(diǎn)參數(shù)
FileOutputStream fos = null;
//創(chuàng)建對(duì)象輸出流引用--將java序列化寫(xiě)出的流
ObjectOutputStream oos = null;
//創(chuàng)建實(shí)際的文件輸出流對(duì)象--指定輸出路徑
fos = new FileOutputStream("stu");
//創(chuàng)建實(shí)際的對(duì)象輸出流對(duì)象剩胁,使用節(jié)點(diǎn)流參數(shù)
oos = new ObjectOutputStream(fos);
//將java對(duì)象序列化寫(xiě)出
oos.writeObject(stu);
//刷新輸出流
oos.flush();
//關(guān)閉流資源
if (fos != null){
fos.close();
}
if (oos != null){
oos.close();
}
}
6.3 序列化與反序列化<Serilizable接口>
- 概念
Serilizable接口是一個(gè)序列化接口,是標(biāo)記接口祥国,該接口內(nèi)沒(méi)有任何方法昵观。實(shí)現(xiàn)該接口只是作為一個(gè)標(biāo)記給JVM看,然后JVM認(rèn)為實(shí)現(xiàn)了該接口的類(lèi)型對(duì)象可以進(jìn)行序列化舌稀,因此該類(lèi)的所有屬性和方法都會(huì)自動(dòng)序列化啊犬,不必關(guān)心具體序列化的過(guò)程。 -
圖解
對(duì)象序列化與反序列化圖解.png - 前提
需要進(jìn)行序列化或反序列化的對(duì)象必須實(shí)現(xiàn)Serilizable接口壁查。
//必須實(shí)現(xiàn)Serilizable接口作為JVM認(rèn)可的序列化標(biāo)記
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//提供get()和set()方法觉至,并重寫(xiě)toString()方法
}
6.3.1 序列化
- 概念
對(duì)象流將 Java對(duì)象轉(zhuǎn)換成二進(jìn)制 寫(xiě)入磁盤(pán)的過(guò)程叫做序列化,底層采用輸出流作為節(jié)點(diǎn)流參數(shù)潮罪。 - 特點(diǎn)
每一個(gè)java對(duì)象都會(huì)是較大的文件康谆,因此序列化時(shí),對(duì)象輸出流會(huì)將Java對(duì)象進(jìn)行切割分段嫉到,再寫(xiě)入到硬盤(pán)文件當(dāng)中沃暗。 - 代碼示例
//創(chuàng)建需要序列化的java對(duì)象
Student stu = new Student("haha",21);
//創(chuàng)建對(duì)象輸出流引用--序列化使用的寫(xiě)出流
ObjectOutputStream obj = null;
try {
//創(chuàng)建實(shí)際的對(duì)象輸出流對(duì)象--采用文件輸出流作為參數(shù),指定序列化路徑
obj = new ObjectOutputStream(new FileOutputStream("students"));
//將需要序列化的java對(duì)象寫(xiě)出序列化到硬盤(pán)中
obj.writeObject(stu);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (obj != null){
try {
obj.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 注意點(diǎn)
- 序列化多個(gè)對(duì)象:當(dāng)需要同時(shí)序列化多個(gè)對(duì)象時(shí)何恶,提前將多個(gè)對(duì)象存儲(chǔ)到數(shù)組或集合當(dāng)中<建議使用泛型>孽锥,在序列化時(shí)ObjectOutputStream.writeObject(集合對(duì)象)即可一次序列化多個(gè)對(duì)象。采用集合序列化多個(gè)對(duì)象到硬盤(pán)中的文件细层,存儲(chǔ)的也是一個(gè)集合對(duì)象惜辑,而不是散開(kāi)的單個(gè)泛型對(duì)象。
- 若想采用每次序列化單個(gè)對(duì)象的方式逐次序列化多個(gè)對(duì)象疫赎,那么會(huì)在序列化到第二個(gè)對(duì)象時(shí)出現(xiàn)錯(cuò)誤盛撑。
6.3.2 反序列化
- 概念
對(duì)象流從磁盤(pán)讀出完整 Java 對(duì)象到內(nèi)存中的過(guò)程叫做反序列化,底層采用輸入流作為節(jié)點(diǎn)流參數(shù)捧搞。 - 代碼示例
//創(chuàng)建反序列化的對(duì)象輸入流引用
ObjectInputStream ois = null;
try {
//創(chuàng)建實(shí)際的對(duì)象輸入流對(duì)象抵卫,使用文件輸入流作為參數(shù)
ois = new ObjectInputStream( new FileInputStream("c:/Person.dat"));
//反序列化,將對(duì)象從磁盤(pán)讀出胎撇,并轉(zhuǎn)化為對(duì)應(yīng)類(lèi)型的對(duì)象
Person person = (Person)ois.readObject();
//獲取反序列化后對(duì)象的屬性
System.out.println(person.name);
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally { //關(guān)閉流介粘,釋放資源
try {
if (ois != null) {
ois.close();
}
}catch(IOException e) {}
}
-
注意點(diǎn)
反序列化多個(gè)對(duì)象:若序列化文件中的對(duì)象是集合對(duì)象(即使集合里面存儲(chǔ)了多個(gè)泛型對(duì)象),那么反序列化時(shí) ObjectInputStream.readObject()讀取返回的obj也是一個(gè)集合對(duì)象晚树,因此返回時(shí)可以采用集合引用<建議使用泛型>來(lái)接收返回的集合對(duì)象姻采。再對(duì)返回的集合對(duì)象進(jìn)行迭代遍歷和獲取集合元素(單個(gè)對(duì)象)的信息。
6.4 transient關(guān)鍵字
- 概念
transient意為游離的爵憎。在一個(gè)需要序列化的類(lèi)中慨亲,明確有些屬性需要序列化婚瓜,而其他屬性不需要被序列化時(shí),使用transient關(guān)鍵字修飾該屬性將不會(huì)被序列化巡雨。 - 作用
只需要實(shí)現(xiàn)Serilizable接口闰渔,將不需要序列化的屬性添加關(guān)鍵字transient修飾席函,序列化對(duì)象的時(shí)候铐望,該屬性就不會(huì)序列化。 - 使用場(chǎng)景
如一個(gè)用戶(hù)類(lèi)有一些敏感信息<密碼茂附,銀行卡號(hào)>正蛙,為了安全起見(jiàn),不希望在網(wǎng)絡(luò)操作中被傳輸(被序列化营曼,包括本地序列化緩存)乒验。因此在該屬性上加上 transient關(guān)鍵字,以免被序列化蒂阱。即transient修飾的字段的生命周期僅存于調(diào)用者的內(nèi)存中锻全,而不會(huì)寫(xiě)到磁盤(pán)里持久化。
class Person implements Serializable{
String name;
transient String password;//采用 transient 關(guān)鍵字修飾此屬性录煤,序列化時(shí)會(huì)忽略<即不會(huì)被序列化>
}
6.5 serialVersionUID 屬性
- 概念
serialVersionUID 意為序列化版本號(hào)鳄厌,序列化的對(duì)象在存儲(chǔ)時(shí)都有一個(gè)標(biāo)識(shí)版本號(hào),使用該屬性修飾的類(lèi)保證了序列化版本號(hào)唯一妈踊。 - 特點(diǎn)
- serialVersionUID屬性使用public static final修飾了嚎;
- 若不使用序列化版本號(hào),在多次對(duì)原類(lèi)修改添加后進(jìn)行序列化時(shí)廊营,會(huì)產(chǎn)生多個(gè)版本不一樣的對(duì)象歪泳,反序列化時(shí)也會(huì)不清楚到底反序列化哪一個(gè)版本;
- 實(shí)現(xiàn)Serilizable接口時(shí)露筒,系統(tǒng)默認(rèn)提供序列化版本號(hào)呐伞,但是強(qiáng)烈建議程序員自定義類(lèi)時(shí)手動(dòng)添加寫(xiě)上。
- 作用
- java驗(yàn)證類(lèi)唯一性的標(biāo)志之一:java的序列化機(jī)制是通過(guò)判斷類(lèi)的序列化ID號(hào)來(lái)驗(yàn)證 序列化對(duì)象版本一致性的慎式;
- 保證序列化與反序列化的文件相同且唯一:擁有serialVersionUID屬性修飾的類(lèi)伶氢,即使其實(shí)例對(duì)象在進(jìn)行一次序列化,之后無(wú)論對(duì)該對(duì)象進(jìn)行多少次添加或修改瞬捕,重新對(duì)"新對(duì)象"序列化時(shí)鞍历,得到的還是同一個(gè)對(duì)象;
- 防止序列化兼容問(wèn)題:解決序列化時(shí)對(duì)象不唯一問(wèn)題肪虎,對(duì)象修改后也不出現(xiàn)序列化的版本問(wèn)題劣砍,而是擁有統(tǒng)一的版本號(hào)。
-
圖解serialVersionUID
serialVersionUID圖解.png - 使用方式
class Person implements Serializable{
//加入版本號(hào)扇救,防止序列化兼容問(wèn)題刑枝,解決序列化時(shí)不一致
private static final long serialVersionUID = -11111111L;
String name;
int age;
boolean sex;
}
- IDEA生成序列化版本號(hào)
File --> Settings --> Editor --> Inspections -->搜索serializable --> Serializable Class without serialVersionUID --> 打鉤 --> ok --> 對(duì)實(shí)現(xiàn)了Serializable接口的類(lèi) atl+回車(chē) --> Add serialVersionUID
七香嗓、數(shù)據(jù)流<DataStream>
- 概念
數(shù)據(jù)流既是數(shù)據(jù)專(zhuān)屬的流,用于讀取文件中的數(shù)據(jù)及其數(shù)據(jù)類(lèi)型装畅,或用于寫(xiě)出數(shù)據(jù)及其數(shù)據(jù)類(lèi)型靠娱,數(shù)據(jù)流讀取保存或?qū)懭肷傻奈募皇瞧胀ㄎ谋疚募荒苤苯哟蜷_(kāi)掠兄。 - 分類(lèi)
- DataOutputStream:數(shù)據(jù)輸出流像云,可以將數(shù)據(jù)連同數(shù)據(jù)的類(lèi)型一并寫(xiě)入文件,寫(xiě)出的文件不是普通文本文件蚂夕;
- DataInputStream:數(shù)據(jù)輸入流迅诬,對(duì)于DataOutputStream寫(xiě)出的文件,只能使用DataInputStream流去讀婿牍,并且讀取時(shí)需要提前知道寫(xiě)入時(shí)的數(shù)據(jù)順序侈贷。讀的順序需要和寫(xiě)的順序一致。才可以正常取出數(shù)據(jù)等脂。
- 作用特點(diǎn)
- 安全性:使用DataOutputStream寫(xiě)出的數(shù)據(jù)連帶其數(shù)據(jù)類(lèi)型俏蛮,更加安全易讀;
- 加密性:對(duì)于DataOutputStream寫(xiě)出的文件必須要DataInputStream流去讀上遥,否則亂碼搏屑,更加安全加密。
- DataOutputStream
FileOutputStream fos = new FileOutputStream("data");
// 創(chuàng)建數(shù)據(jù)專(zhuān)屬的字節(jié)輸出流--使用節(jié)點(diǎn)流
DataOutputStream dos = new DataOutputStream(fos);
//合并--
//DataOutputStream dos = new DataOutputStream(new FileOutputStream("data"));
// 寫(xiě)數(shù)據(jù)
byte b = 100;
short s = 200;
int i = 300;
long l = 400L;
float f = 3.0F;
double d = 3.14;
boolean sex = false;
char c = 'a';
// 把數(shù)據(jù)以及數(shù)據(jù)的類(lèi)型一并寫(xiě)入到文件當(dāng)中露该。
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeLong(l);
dos.writeFloat(f);
dos.writeDouble(d);
dos.writeBoolean(sex);
dos.writeChar(c);
// 寫(xiě)出完成時(shí)睬棚,刷新管道
dos.flush();
// 關(guān)閉外層流(包裝流)
dos.close();
- DataInputStream
FileInputStream fis = new FileInputStream("data");
// 創(chuàng)建數(shù)據(jù)專(zhuān)屬的字節(jié)輸入流--使用節(jié)點(diǎn)流
DataInputStream dis = new DataInputStream(fis);
//合并--
DataInputStream dis = new DataInputStream(new FileInputStream("data"));
// 開(kāi)始讀取DataOutputStream寫(xiě)出的文件--前提知道寫(xiě)出的數(shù)據(jù)順序
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
boolean sex = dis.readBoolean();
char c = dis.readChar();
//關(guān)閉流資源
dis.close();
八、File 類(lèi)
- 概念
File 類(lèi)是文件和目錄路徑名的抽象表示形式解幼,指的是一類(lèi)可以直接對(duì)文件進(jìn)行操作的類(lèi)(不管是硬盤(pán)上的還是內(nèi)存緩存中的)抑党。 - 特點(diǎn)
File類(lèi)不是具體的文件,只是一條路徑撵摆,可以是目錄也可以是具體文件所在目錄底靠,底層封裝了文件的路徑和路徑狀態(tài)。 - 字段
- String path:文件的路徑特铝,可以是根目錄或絕對(duì)路徑暑中;
- PathStatus status = null:路徑的狀態(tài),
- enum PathStatus { INVALID, CHECKED }:
- int prefixLength:文件前綴長(zhǎng)度鲫剿;
- char separatorChar = fs.getSeparator():文件分隔符鳄逾。
- 常用方法
- File(String pathname):構(gòu)造方法,根據(jù)指定路徑創(chuàng)建一個(gè)File文件類(lèi)對(duì)象灵莲;
- File(String parent, String child):構(gòu)造方法雕凹,
- String getName():
- booLean exists():判斷 根據(jù)指定路徑創(chuàng)建的文件類(lèi)對(duì)象是否存在,即在指定路徑下是否能找到對(duì)應(yīng)文件;
- boolean createNewFile():若指定路徑下的文件類(lèi)對(duì)象不存在枚抵,則在該路徑下以文件形式創(chuàng)建相應(yīng)的文件线欲;
- boolean mkdir():若指定路徑下的文件類(lèi)對(duì)象不存在,則在該路徑下以目錄形式創(chuàng)建相應(yīng)的目錄文件汽摹;
- boolean mkdirs():若指定路徑下的文件類(lèi)對(duì)象不存在李丰,則在該路徑下以多級(jí)目錄形式創(chuàng)建相應(yīng)的目錄文件;
- String getParent():獲取此路徑下創(chuàng)建的文件類(lèi)對(duì)象的文件父目錄逼泣;
- File getParentFile():獲取此路徑下創(chuàng)建的文件類(lèi)對(duì)象的文件父目錄趴泌,并根據(jù)該目錄生成新的文件類(lèi)對(duì)象;
- String getPath():獲取該文件類(lèi)對(duì)象的原文件路徑圾旨;
- String getAbsolutePath():獲取該文件類(lèi)對(duì)象的文件絕對(duì)路徑踱讨;
- boolean isDirectory():判斷該文件類(lèi)對(duì)象是否是一個(gè)目錄魏蔗;
- boolean isFile():判斷該文件類(lèi)對(duì)象是否是一個(gè)文件砍的;
- boolean isHidden():判斷該文件類(lèi)對(duì)象是否是一個(gè)隱藏文件;
- long lastModified(): 獲取該文件類(lèi)對(duì)象的文件最后一次的修改時(shí)間莺治,返回的是自1970年1月1日開(kāi)始的毫秒數(shù)廓鞠;
- long length():獲取該文件類(lèi)對(duì)象的文件大小谣旁;
- File[] listFiles():獲取當(dāng)前目錄下所有的子文件床佳,返回的是由多級(jí)子目錄構(gòu)成的文件數(shù)組,可通過(guò)foreach循環(huán)遍歷該數(shù)組得到所有的子文件榄审。
- 代碼實(shí)例
//根據(jù)指定路徑創(chuàng)建一個(gè)文件類(lèi)對(duì)象
File f = new File("");
// 判斷該路徑下的創(chuàng)建的文件類(lèi)對(duì)象 (文件)是否存在
System.out.println(f.exists());
// 如果路徑下文件不存在砌们,則以文件的形式創(chuàng)建出來(lái)
/*if(!f1.exists()) {
// 以文件形式新建
f1.createNewFile();
}*/
// 如果路徑下文件不存在,則以單級(jí)目錄的形式創(chuàng)建出來(lái)
/*if(!f1.exists()) {
// 以目錄的形式新建搁进。
f1.mkdir();
}*/
// 如果路徑下文件不存在浪感,則以多級(jí)目錄的形式創(chuàng)建出來(lái)
File f2 = new File("D:/a/b/c/d/e/f");
/*if(!f2.exists()) {
// 以多重目錄的形式新建。
f2.mkdirs();
}*/
File f3 = new File("D:\\course\\01-開(kāi)課\\學(xué)習(xí)方法.txt");
// 獲取文件的父路徑
String parentPath = f3.getParent();
// 獲取文件的父路徑文件
File parentFile = f3.getParentFile();
//獲取文件的絕對(duì)路徑
System.out.println("獲取絕對(duì)路徑:" + parentFile.getAbsolutePath());
常見(jiàn)面試題
- 使用字節(jié)文件流實(shí)現(xiàn)一個(gè)文件的復(fù)制饼问?
答:
創(chuàng)建字節(jié)輸入流對(duì)象FileInputStream影兽;
創(chuàng)建字節(jié)輸出流對(duì)象FileOutPutStream;
輸入流對(duì)象從指定路徑下read()讀取文件莱革,并將讀取的內(nèi)容使用字節(jié)數(shù)組byte[]存儲(chǔ)峻堰;
使用變量返回值判斷文件是否有內(nèi)容可讀;
輸出流對(duì)象將輸入流讀取的字節(jié)數(shù)組中的內(nèi)容write()寫(xiě)出盅视;
刷新輸出流捐名;
關(guān)閉所有流,釋放資源闹击;
重點(diǎn):一邊讀镶蹋,一邊寫(xiě),每次讀取多少個(gè)就寫(xiě)出多少個(gè)。
public class StreamCopyTest {
public static void main(String[] args) {
//創(chuàng)建字節(jié)輸入流引用
FileInputStream fis = null;
//創(chuàng)建字節(jié)輸出流引用
FileOutputStream fos = null;
try {
//創(chuàng)建實(shí)際的字節(jié)輸入流對(duì)象
fis = new FileInputStream("");
//創(chuàng)建實(shí)際的字節(jié)輸出流對(duì)象--輸出文件若存在則覆蓋梅忌,不存在則新建
fos = new FileOutputStream("");
//創(chuàng)建字節(jié)數(shù)組存儲(chǔ)輸入流讀取的數(shù)據(jù)
byte[] bs = new byte[1024 * 1024];//1024kb = 1byte,1mb = 1024kb
//用于計(jì)算每次讀取文件返回的字節(jié)個(gè)數(shù)狰腌,-1表示已讀到文件末尾
int readcount = 0;
//一邊讀取,一邊輸出牧氮,讀取多少個(gè)琼腔,輸出多少個(gè)
while ((readcount = fis.read(bs)) != -1){
fos.write(bs,0,readcount);
}
//輸出完成時(shí),必須刷新管道
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//關(guān)閉流資源踱葛,釋放內(nèi)存
if (fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 使用字符文件流實(shí)現(xiàn)一個(gè)文件的復(fù)制丹莲?
答:
創(chuàng)建字符輸入流對(duì)象FileReader
創(chuàng)建字符輸出流對(duì)象FileWriter
創(chuàng)建字符數(shù)組char[]存儲(chǔ)字符輸入流read讀取的文件數(shù)據(jù)
定義變量返回值 判斷文件是否有數(shù)據(jù)可讀
字符輸入流從文件讀取數(shù)據(jù)
字符輸出流將讀取到的數(shù)據(jù)寫(xiě)出到文件
刷新輸出流
關(guān)閉所有資源
public class WriterCopyTest {
public static void main(String[] args) {
//創(chuàng)建字符輸入流引用
FileReader fr = null;
//創(chuàng)建字符輸出流引用
FileWriter fw = null;
try {
//創(chuàng)建實(shí)際的字符輸入流對(duì)象
fr = new FileReader("");
//創(chuàng)建實(shí)際的字符輸出流對(duì)象,若輸出文件已存在則覆蓋尸诽,若不存在則新建
fw = new FileWriter("");
//創(chuàng)建字符數(shù)組存儲(chǔ)輸入流每一次讀取的數(shù)據(jù)
char[] cs = new char[1024*1024];
//用于判斷每一次讀取文件返回的字節(jié)個(gè)數(shù)甥材,-1表示已讀到文件末尾
int readchar = 0;
//一邊讀取,一邊寫(xiě)出性含,讀取多少個(gè)寫(xiě)出多少個(gè)
while ((readchar = fr.read(cs)) != -1){
fw.write(cs,0,readchar);
}
//輸出完成時(shí)洲赵,必須刷新管道
fw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//關(guān)閉流資源,釋放內(nèi)存
if (fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 使用一個(gè)字節(jié)緩沖流 或 字符緩沖流實(shí)現(xiàn)一個(gè)文件的復(fù)制商蕴?
答:
BufferInputStream和BufferOutPutStream
BufferReader和BufferWriter
- 實(shí)現(xiàn)從D盤(pán)的多個(gè)目錄及文件復(fù)制到C盤(pán)下叠萍?
答:
使用File類(lèi)獲取得到多個(gè)目錄(數(shù)組)
遍歷File數(shù)組中得到的所有File對(duì)象
判斷File數(shù)組中的File對(duì)象是目錄還是文件
(是目錄繼續(xù)往下遍歷,是文件則直接復(fù)制到另外一個(gè)盤(pán)下)
確定源目錄的路徑 和 目標(biāo)目錄的路徑
對(duì)File對(duì)象采用IO流進(jìn)行邊讀邊寫(xiě)
如何確定對(duì)應(yīng)的目錄路徑绪商?
public static void main(String[] args) {
// 拷貝源
File srcFile = new File("D:\\course\\02-JavaSE\\document");
// 拷貝目標(biāo)
File destFile = new File("C:\\a\\b\\c");
// 調(diào)用方法完成拷貝
copyDir(srcFile, destFile);
}
/**
* 拷貝目錄
* @param srcFile 拷貝源
* @param destFile 拷貝目標(biāo)
*/
private static void copyDir(File srcFile, File destFile) {
if(srcFile.isFile()) {
// srcFile如果是一個(gè)文件(文件下面不再有目錄)苛谷,遞歸結(jié)束
// 并且是文件即需要拷貝,復(fù)制--一邊讀一邊寫(xiě)
FileInputStream in = null;
FileOutputStream out = null;
try {
// 從源路徑讀取文件
in = new FileInputStream(srcFile);
// 處理得出要復(fù)制到的目標(biāo)路徑--路徑的轉(zhuǎn)換很難很重要格郁,需要多重字符串截取和拼接
//先獲取目標(biāo)路徑的盤(pán)符根目錄--再對(duì)源路徑盤(pán)符下的子目錄路徑進(jìn)行復(fù)制拼接
String path = (destFile.getAbsolutePath().endsWith("\\") ? destFile.getAbsolutePath() : destFile.getAbsolutePath() + "\\") + srcFile.getAbsolutePath().substring(3);
//將讀取的文件寫(xiě)入到新的盤(pán)符目錄下
out = new FileOutputStream(path);
// 一邊讀一邊寫(xiě)腹殿,
byte[] bytes = new byte[1024 * 1024]; // 一次復(fù)制1MB
int readCount = 0;
while((readCount = in.read(bytes)) != -1){
out.write(bytes, 0, readCount);
}
//寫(xiě)入完成時(shí)刷新管道
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{ //關(guān)閉流資源,釋放內(nèi)存
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return;
}
// 獲取源路徑下的所有子目錄(文件)
File[] files = srcFile.listFiles();
for(File file : files){
// 獲取所有文件(包括目錄和文件)的絕對(duì)路徑
//若是源路徑下的File是一個(gè)目錄例书,則在目標(biāo)盤(pán)符下創(chuàng)建對(duì)應(yīng)目錄锣尉;若是一個(gè)File文件,則結(jié)束遞歸開(kāi)始復(fù)制
if(file.isDirectory()){
// 在目標(biāo)盤(pán)符下新建對(duì)應(yīng)的目錄
//D:\course\02-JavaSE\document\JavaSE進(jìn)階講義 源目錄
//C:\course\02-JavaSE\document\JavaSE進(jìn)階講義 目標(biāo)目錄
//源file目錄
String srcDir = file.getAbsolutePath();
//新file要復(fù)制到的新目錄
String destDir = (destFile.getAbsolutePath().endsWith("\\") ? destFile.getAbsolutePath() : destFile.getAbsolutePath() + "\\") + srcDir.substring(3);
//使用新目錄創(chuàng)建出File文件對(duì)象
File newFile = new File(destDir);
if(!newFile.exists()){
newFile.mkdirs();
}
}
// 遞歸調(diào)用--很難想到使用遞歸
copyDir(file, destFile);
}
}