網(wǎng)站建設(shè)3要素關(guān)鍵詞優(yōu)化包含
今日內(nèi)容
上課同步視頻:CuteN饕餮的個人空間_嗶哩嗶哩_bilibili
同步筆記沐沐霸的博客_CSDN博客-Java2301
零、 復習昨日
一、作業(yè)
二、緩沖流
三、字符流
四、緩沖字符流
五、匿名內(nèi)部類
零、 復習昨日
File: 通過路徑代表一個文件或目錄
方法: 創(chuàng)建型,查找類,判斷類,其他IO
- 輸入& 輸出
- 字節(jié)&字符
try-catch代碼
一、作業(yè)
給定路徑刪除該文件夾
public static void main(String[] args) {deleteDir(new File("E:\\A"));}// 刪除文件夾public static void deleteDir(File file) {File[] files = file.listFiles( );for (File file1 : files) {if(file1.isFile()) { // 如果是文件,直接刪除file1.delete();} else {deleteDir(file1);}}file.delete(); // 刪除空文件夾}
二、緩沖字節(jié)流
演示: 拷貝一首歌
public static void main(String[] args) throws Exception {// 拷貝歌曲,耗時 183372毫秒long begin = System.currentTimeMillis( );FileInputStream fis = new FileInputStream("E:\\Angel.mp3");FileOutputStream fos = new FileOutputStream("E:\\Angel2.mp3");int b = -1;while((b = fis.read()) != -1) {fos.write(b);}fis.close();fos.close();long end = System.currentTimeMillis( );System.out.println("拷貝歌曲,耗時 " + (end - begin) + "毫秒" );}
很慢很慢~~~
原因: 一次讀寫一個字節(jié),但是歌曲10M有1100萬多個字節(jié)…
那么,如果可以一次讀多個,寫多個不就快了嗎?! 是!! 那就是我們的緩沖區(qū)字節(jié)流
緩沖區(qū)字節(jié)輸入流 BufferedInputStream,緩沖區(qū)字節(jié)輸出流 BufferedOutputStream
之所以快,是因為它們內(nèi)部有一個緩沖區(qū)數(shù)組
(長度8192),在一次讀取或者寫出的時候通過數(shù)組完成,即一次讀取或者寫出多個使用緩存區(qū)輸入/輸出流,需要給構(gòu)造方法傳入對應輸入/輸出流
?

public static void main(String[] args) throws Exception {// 拷貝歌曲,耗時 183372毫秒long begin = System.currentTimeMillis( );FileInputStream fis = new FileInputStream("E:\\Angel.mp3");FileOutputStream fos = new FileOutputStream("E:\\Angel2.mp3");// 創(chuàng)建緩沖區(qū)輸入.輸出流BufferedInputStream bis = new BufferedInputStream(fis);BufferedOutputStream bos = new BufferedOutputStream(fos);int b = -1;while((b = bis.read()) != -1) {bos.write(b);}bis.close();bos.close();// 內(nèi)部是數(shù)組傳輸數(shù)據(jù),最后一次輸出數(shù)據(jù)時,數(shù)組不一定裝滿// 如果執(zhí)行close,會關(guān)流的同時會強制刷新剩余數(shù)據(jù)輸出// 也可以執(zhí)行flush手動刷新// bos.flush();long end = System.currentTimeMillis( );System.out.println("拷貝歌曲,耗時 " + (end - begin) + "毫秒" );}
三、字符流
字節(jié)流適合讀取二進制文件,讀取字符數(shù)據(jù)可能會亂碼!
建議讀取字符,采用字符流!
字符流有兩個抽象父類
- Reader (字符輸入流 )
- Writer (字符輸出流)
一般使用其子類
- FileReader
- FileWriter
3.1 FileReader
構(gòu)造方法
- FileReader(File file) 在給定從中讀取數(shù)據(jù)的 File 的情況下創(chuàng)建一個新 FileReader。
- FileReader(String fileName) 在給定從中讀取數(shù)據(jù)的文件名的情況下創(chuàng)建一個新 FileReader。
方法
- int read() 讀取單個字符。
讀完末尾返回-1
- int read(char[] cbuf) 將字符讀入數(shù)組。
- void close() 關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源。
public static void main(String[] args) throws Exception {FileReader fr = new FileReader("a.txt");int ch = -1;while((ch = fr.read()) != -1) {System.out.println((char)ch );}fr.close();}
FileReader fr = new FileReader("a.txt");char[] chars = new char[4]; // 創(chuàng)建空字符數(shù)組fr.read(chars); // 一次讀取數(shù)組長度個字符,存儲到數(shù)組中System.out.println(Arrays.toString(chars ) );fr.close();
3.2 FileWriter
FileWriter在創(chuàng)建時,內(nèi)部默認構(gòu)造一個緩沖數(shù)組,用于一次寫出多個,大小是1024字節(jié)
構(gòu)造方法
- FileWriter(File file) 根據(jù)給定的 File 對象構(gòu)造一個 FileWriter 對象。
- FileWriter(File file, boolean append) 根據(jù)給定的 File 對象構(gòu)造一個 FileWriter 對象。
- FileWriter(String fileName) 根據(jù)給定的文件名構(gòu)造一個 FileWriter 對象。
- FileWriter(String fileName, boolean append) 根據(jù)給定的文件名以及指示是否附加寫入數(shù)據(jù)的 boolean 值來構(gòu)造 FileWriter 對象。
append指定成true,在原文件后面追加,指定成false,覆蓋原文件
如果不知道,默認就是false
方法
- void close() 關(guān)閉此流,但要先刷新它。
- void flush() 刷新該流的緩沖。
- void write(char[] cbuf) 寫入字符數(shù)組。
- void write(int c) 寫入單個字符。
- void write(String str) 寫入字符串。
- void write(String str, int off, int len) 寫入字符串的某一部分。
public static void main(String[] args) throws Exception {FileWriter fw = new FileWriter("a.txt");// 寫字符fw.write('j');// 寫字符串fw.write("java");// 寫字符數(shù)組char[] chars = {'a','b','c'};fw.write(chars);// 寫字符串中一部分內(nèi)容String str = "javabigdata";fw.write(str,4,3);// 因為有緩沖區(qū),不關(guān)流的話有些數(shù)據(jù)無法輸出// 因為沒有達到緩沖區(qū)大小//fw.close();// 也可以強制刷新出來fw.flush();}
3.3 練習 復制小說
使用 踹凱吃 來完成
public static void main(String[] args) {long begin = System.currentTimeMillis( );FileReader fr = null;FileWriter fw = null;try {fr = new FileReader("E:\\《雪中悍刀行》.txt");fw = new FileWriter("E:\\血刀.txt");int ch = -1;while((ch = fr.read()) != -1) {fw.write(ch);}} catch (Exception e) {e.printStackTrace( );} finally {try {fr.close();fw.close();} catch (IOException e) {e.printStackTrace( );}}long end = System.currentTimeMillis( );System.out.println("拷貝小說,耗時 " + (end - begin) + "毫秒" );}
3.4 練習
使用字符流把a文件中的數(shù)據(jù)轉(zhuǎn)換后寫到b文件中
要求:1) 大寫轉(zhuǎn)換為小寫 2)小寫轉(zhuǎn)換為大寫 3)刪除數(shù)字
四、緩沖字符流
BufferedReader BufferedWriter
緩沖區(qū)字符輸入輸出流,內(nèi)部在創(chuàng)建對象時會構(gòu)建一個長度為8192的緩沖數(shù)組.ps: 查看構(gòu)造方法源碼…
BufferedReader
構(gòu)造方法
- BufferedReader(Reader in) 創(chuàng)建一個使用默認大小輸入緩沖區(qū)的緩沖字符輸入流。
方法
- int read() 讀取單個字符。
- String readLine() 讀取一個文本行。
- void close() 關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源。
BufferedWriter
構(gòu)造方法
- BufferedWriter(Writer out) 創(chuàng)建一個使用默認大小輸出緩沖區(qū)的緩沖字符輸出流。
方法
- void close() 關(guān)閉此流,但要先刷新它。
- void flush() 刷新該流的緩沖。
- void newLine() 寫入一個行分隔符。
- void write(int c) 寫入單個字符。
- void write(String s) 寫入字符串
public static void main(String[] args) {long begin = System.currentTimeMillis( );FileReader fr = null;FileWriter fw = null;BufferedReader br = null;BufferedWriter bw = null;try {fr = new FileReader("E:\\《雪中悍刀行》.txt");fw = new FileWriter("E:\\血刀.txt");br = new BufferedReader(fr);bw = new BufferedWriter(fw);int ch = -1;// 一次讀一個放入緩沖區(qū)// while((ch = br.read()) != -1) {// bw.write(ch);// 寫一個字符// }String line = null;// 一次讀取一行,讀取到換行終止符結(jié)束并返回,但是不包含終止符while((line = br.readLine()) != null) {bw.write(line); // 寫一行字符串// 寫出一個換行符// bw.write("\r\n");bw.newLine();}} catch (Exception e) {e.printStackTrace( );} finally {try {br.close();bw.close();} catch (IOException e) {e.printStackTrace( );}}long end = System.currentTimeMillis( );System.out.println("拷貝小說,耗時 " + (end - begin) + "毫秒" );}
練習
讀取一個文本,按行倒著輸出,即讀取的第一行輸出在最后一行,讀取的第二行,輸出在倒數(shù)第二行.
思路: 不能讀完直接輸出了,而是讀一行,向集合中存一行.讀取完畢后,倒著遍歷集合即可
public static void main(String[] args) {long begin = System.currentTimeMillis( );BufferedReader br = null;BufferedWriter bw = null;try {br = new BufferedReader(new FileReader("E:\\a.txt"));bw = new BufferedWriter(new FileWriter("E:\\a2.txt"));ArrayList<String> list = new ArrayList<>( );// 讀取每一行,轉(zhuǎn)入集合String line = null;while((line = br.readLine()) != null) {list.add(line);}// 倒著遍歷集合for (int i = list.size() - 1;i >= 0;i--) {String s = list.get(i);bw.write(s);bw.newLine();}} catch (Exception e) {e.printStackTrace( );} finally {try {br.close();bw.close();} catch (IOException e) {e.printStackTrace( );}}long end = System.currentTimeMillis( );System.out.println("倒著拷貝,耗時 " + (end - begin) + "毫秒" );}
練習
1. 將上面歌詞內(nèi)容存放到本地磁盤D根目錄,文件命名為 `word.txt`
2. 選擇合適的IO流讀取word.txt文件的內(nèi)容
3. 統(tǒng)計每個單詞出現(xiàn)的次數(shù)(單詞忽略大小寫)
4. 如果出現(xiàn)組合單詞如 `you're`按一個單詞處理
5. 將統(tǒng)計的結(jié)果存儲到本地磁盤D根目錄下的`wordcount.txt`文件
【該題使用緩沖字符流更好】
wordcout.txt每行數(shù)據(jù)個數(shù)如下
you --> 9次
my --> 9次
I --> 9次
public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new FileReader("E:\\word.txt"));BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\wordcount.txt"));// TreeMap會有排序效果TreeMap<String, Integer> map = new TreeMap<>( );String line = null;while((line = br.readLine()) != null) {// 將每行字符串拆分成單個單詞String[] strArr = line.split(" ");for (String s : strArr) {// 將每個單詞全部轉(zhuǎn)成小寫String lowerStr = s.toLowerCase( );// 判斷是否存在if (map.containsKey(lowerStr)) {Integer count = map.get(lowerStr); // 如果存在,則取出count++; // 次數(shù)+1map.put(lowerStr,count); // 再存入} else {map.put(lowerStr,1); // 如果不包含,即第一次存,次數(shù)1}}}// 輸出Set<Map.Entry<String, Integer>> entrySet = map.entrySet( );for (Map.Entry<String, Integer> entry : entrySet) {String word = entry.getKey( );Integer count = entry.getValue( );bw.write(word + " ---> "+count+"次");bw.newLine();}br.close();bw.close();}
五、IO流總結(jié)
畫思維導圖 https://www.processon.com/view/link/6360e893f346fb33540a61c1 訪問密碼:2301
六、匿名內(nèi)部類
ps: 為了明天講多線程做準備,會用到匿名內(nèi)部類這個知識
思考一個問題?
假如有一個接口,現(xiàn)在讓你創(chuàng)建一個接口的實現(xiàn)類對象,該怎么做?
換句話,有個方法,參數(shù)列表是接口,應該如何調(diào)用?
解決:
? 先創(chuàng)建一個類,實現(xiàn)接口,重寫方法
創(chuàng)建對象
現(xiàn)在有個更簡單的寫法,可以不用創(chuàng)建類就可以實現(xiàn)出一個接口的實現(xiàn)類
// 接口
public interface USB {void run();
}
public static void main(String[] args) {// 有一個接口,現(xiàn)在讓你創(chuàng)建一個接口的實現(xiàn)類對象// new USBImpl();// test(new USBImpl());// 就相當于是創(chuàng)建了USB接口的實現(xiàn)類,并且重寫了方法// 這就是匿名內(nèi)部類test(new USB(){@Overridepublic void run() {System.out.println("匿名實現(xiàn).." );}});// 這樣是將匿名內(nèi)部類,取了名字叫usbUSB usb = new USB(){@Overridepublic void run() {System.out.println("匿名實現(xiàn).." );}};test(usb);}public static void test(USB usb) {usb.run();}
總結(jié): 匿名內(nèi)部類就是簡化了創(chuàng)建子類對象的過程.
實戰(zhàn)
使用匿名內(nèi)部類完成. 創(chuàng)建TreeSet時指定比較器.