復(fù)習(xí)
1.字符流
FileWriter FileReader
2.ResourceBundle
3.Properties
a.都可以讀取Properties配置文件
區(qū)別:
a.ResourceBundle是靜態(tài)方法getBundle,Properties成員方法load
b.ResourceBundle一般讀取src根目錄下,Properties一般讀取項目根目錄下
c.ResourceBundle讀取時只需要寫文件名(不帶后綴), Properties讀取時文件名要寫全名
4.異常處理
JDK1.7之前
try{
}catch(Exception e){
}finally{
xxx.close();
}
JDK1.7以及之后
try(FileReader fr = new FileReader("1.txt")){
}catch(Exception e){
}
今日內(nèi)容
- 緩沖流(高效流, 比普通流性能更高)
- 轉(zhuǎn)換流(編碼相關(guān)的流, 指定編碼)'
- 序列化流(操作對象)
- 打印流(System.out.println())
- 設(shè)計模式(裝飾設(shè)計模式, 4個步驟)
- common-io 工具包(簡化io代碼)
緩沖流
緩沖流的介紹
-
介紹
緩沖流,也叫高效流澡腾,是對4個基本的 FileXxx 流的增強(性能增強, 方法基本一樣),所以也是4個流
緩沖流的基本原理缀遍,是在創(chuàng)建流對象時汉买,會創(chuàng)建一個內(nèi)置的默認大小的緩沖區(qū)數(shù)組氏堤,通過緩沖區(qū)讀寫,減少系統(tǒng)IO次數(shù),從而提高讀寫的效率陕赃。
緩沖流的分類
-
按照數(shù)據(jù)類型分類:
緩沖字節(jié)輸入流:
BufferedInputStream
---> 對普通的字節(jié)輸入流``InputStream`增強緩沖字節(jié)輸出流:
BufferedOutputStream
---> 對普通的字節(jié)輸出流OutputStream
增強緩沖字符輸入流:
BufferedReader
---> 對普通的字符輸入流Reader
增強緩沖字符輸出流:
BufferedWriter
---> 對普通的字符輸出流Writer
增強
字節(jié)緩沖流的介紹和使用
-
字節(jié)緩沖流的構(gòu)造
public BufferedInputStream(InputStream in)
:創(chuàng)建一個 新的緩沖輸入流。
public BufferedOutputStream(OutputStream out)
: 創(chuàng)建一個新的緩沖輸出流颁股。 -
字節(jié)緩沖流的使用代碼
(使用一次讀取一個字節(jié)數(shù)組的方式,配合字節(jié)緩沖流使用速度更快)
public static void copy01() throws Exception{ BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.txt")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.txt")); long start = System.currentTimeMillis(); int b = 0; while ((b = bis.read()) != -1) { bos.write(b); } long end = System.currentTimeMillis(); bis.close(); bos.close(); System.out.println(end-start); }
字符緩沖流的介紹和使用
-
字符緩沖流的構(gòu)造
public BufferedReader(Reader in)
:創(chuàng)建一個 新的緩沖輸入流么库。
public BufferedWriter(Writer out)
: 創(chuàng)建一個新的緩沖輸出流。 -
字符緩沖流的特有方法
BufferedRead
:public String readLine()
: 讀一行文字(只要沒到換行)甘有。(讀不到會返回null)
BufferedWriter
:public void newLine()
: 寫一行行分隔符(換行符),由系統(tǒng)屬性定義符號(具有跨平臺性)诉儒。-
BufferedRead的一次讀取一行使用
public static void bwread() throws IOException{ BufferedReader br = new BufferedReader(new FileReader("2.txt")); System.out.println(br.readLine()); //===========一次讀取一行的標準寫法========== String line=""; while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); }
緩沖流練習(xí)
-
public static void main(String[] args) throws IOException {
ArrayList<String> list = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader("1.txt"));
String line ="";
while ((line = br.readLine()) != null) {
list.add(line);
}
br.close();
/* Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.charAt(0)-o1.charAt(0);
}
});*/
Collections.sort(list,((o1, o2) -> o1.charAt(0)-o2.charAt(0)));
/*for (String s : list) {
System.out.println(s);
}*/
BufferedWriter bw = new BufferedWriter(new FileWriter("2"));
for (String s : list) {
bw.write(s);
bw.newLine();
}
bw.close();
}
轉(zhuǎn)換流
編碼和解碼
編碼: 把字符按照某種規(guī)則,將字符轉(zhuǎn)到字節(jié)(二進制)存儲到計算機中亏掀,稱為編碼 忱反。
解碼: 將存儲在計算機中的二進制數(shù)按照某種規(guī)則解析顯示出來,稱為解碼 滤愕。
字符集
字符集 Charset :也叫編碼表温算。是一個系統(tǒng)支持的所有字符的集合,包括各國家文字间影、標點符號注竿、圖形符號吻商、數(shù)字等刑棵。
字符編碼
字符編碼 Character Encoding : 就是一套自然語言的字符與二進制數(shù)之間的對應(yīng)規(guī)則碑幅。
常見的字符集和字符編碼
ASCII 字符集 --> ASCII 編碼 , 規(guī)定了ASCII字符集中所有的字符都占1個字節(jié)(0-127)用于顯示現(xiàn)代英語审孽,主要包括控制字符(回車鍵庸论、退格跷究、換行鍵等)和可顯
示字符(英文大小寫字符肴掷、阿拉伯數(shù)字和西文符號)块蚌。
GBK字符集 ---> GBK編碼, 規(guī)定所有的中文字符都占2個字節(jié)(這2個字節(jié)都是負數(shù)).是為了顯示中文而設(shè)計的一套字符集机蔗。
Unicode字符集 ---> UTF-8編碼, 規(guī)定所有中文字符都占3個字節(jié),Unicode編碼系統(tǒng)為表達任意語言的任意字符而設(shè)計蒲祈,是業(yè)界的一種標準,也稱為統(tǒng)一碼萝嘁、標準萬國碼梆掸。
ISO-8859-1字符集 ---> 用于顯示歐洲使用的語言
編碼引出的問題
IDEA默認使用UTF-8編碼, windows默認使用GBK編碼
public class ReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("E:\\File_GBK.txt");
int read;
while ((read = fileReader.read()) != -1) {
System.out.print((char)read);
}
fileReader.close();
}
}
輸出結(jié)果:
???
使用轉(zhuǎn)換流InputStreamReader
類解決讀取中文的問題
轉(zhuǎn)換流 java.io.InputStreamReader ,是Reader的子類牙言,是從字節(jié)流到字符流的橋梁酸钦。它讀取字節(jié),并使用指定的字符集將其解碼為字符咱枉。它的字符集可以由名稱指定卑硫,也可以接受平臺的默認字符集徒恋。
-
構(gòu)造方法
InputStreamReader(InputStream in)
: 創(chuàng)建一個使用默認字符集的字符流。(使用IDEA默認編碼)
InputStreamReader(InputStream in, String charsetName)
: 創(chuàng)建一個指定字符集的字符流欢伏。(第二個參數(shù)為指定使用何種編碼讀取文件)
使用轉(zhuǎn)換流OutputStreamReader
類寫不同編碼的中文
轉(zhuǎn)換流 java.io.OutputStreamWriter 入挣,是Writer的子類,是從字符流到字節(jié)流的橋梁硝拧。使用指定的字符集將字符編碼為字節(jié)径筏。它的字符集可以由名稱指定,也可以接受平臺的默認字符集障陶。
-
構(gòu)造方法
OutputStreamWriter(OutputStream in)
: 創(chuàng)建一個使用默認字符集的字符流滋恬。
OutputStreamWriter(OutputStream in, String charsetName)
: 創(chuàng)建一個指定字符集的字符流。 -
按指定編碼輸出
public static void main(String[] args) throws Exception { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("1.txt"), "UTF-8"); osw.write("你好"); osw.close(); }
轉(zhuǎn)換流的理解
轉(zhuǎn)換流代碼案例
public static void main(String[] args) throws Exception{
InputStreamReader isr = new InputStreamReader(new FileInputStream("GBK.txt"), "GBK");
OutputStreamWriter ops = new OutputStreamWriter(new FileOutputStream("UTF-8.TXT"), "UTF-8");
int ch=0 ;
while ((ch = isr.read()) != -1) {
ops.write((char)ch);
}
isr.close();
ops.close();
}
序列化
序列化流概述
-
序列化流: 寫出對象的流
ObjectOutputStream(java.io.ObjectOutputStream 類咸这,將Java對象的原始數(shù)據(jù)類型寫出到文件,實現(xiàn)對象的持久存儲夷恍。)
-
反序列化流: 讀取對象的流
ObjectInputStream(ObjectInputStream反序列化流,將之前使用ObjectOutputStream序列化的原始數(shù)據(jù)恢復(fù)為對象媳维。)
ObjectOutputStream類的介紹和使用
-
構(gòu)造方法
public ObjectOutputStream(OutputStream out)
: 創(chuàng)建一個指定OutputStream的ObjectOutputStream。 -
序列化操作的前提
想要序列化, 必須將需要序列化的對象類實現(xiàn)Serializable(可序列化)接口
Serializable接口沒有需要重寫的方法, 這種接口被稱為標記接口
-
序列化操作代碼演示
public static void main(String[] args) throws Exception{ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dog.txt")); oos.writeObject(new Dog(20,"小狗狗")); oos.close(); }
寫出的dog.txt文件中是字節(jié)文件.
ObjectInputStream類的介紹和使用
-
構(gòu)造方法
public ObjectInputStream(InputStream in)
: 創(chuàng)建一個指定InputStream的ObjectInputStream遏暴。 -
反序列化操作代碼演示
public static void main(String[] args) throws Exception{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dog.txt")); Object o = ois.readObject(); System.out.println(o); ois.close(); }
反序列化可能會出現(xiàn)的異常
-
對于JVM可以反序列化對象侄刽,它必須是能夠找到class文件的類。如果找不到該類的class文件朋凉,則拋出一個
ClassNotFoundException
異常州丹。原因: 找不到序列化時的對象類
-
當JVM反序列化對象時,能找到class文件杂彭,但是class文件在序列化對象之后發(fā)生了修改墓毒,那么反序列化操作也會失敗,拋出一個
InvalidClassException
異常亲怠。原因: 修改了序列化的對象類的內(nèi)容,根據(jù)版本號識別
-
Serializable 接口給需要序列化的類所计,提供了一個序列版本號。 serialVersionUID 該版本號的目的在于驗證序列化的對象和對應(yīng)類是否版本匹配团秽。(允許程序員自己管理版本號代碼如下)
public class Employee implements java.io.Serializable { // 加入序列版本號 private static final long serialVersionUID = 1L; public String name; public String address; // 添加新的屬性 ,重新編譯, 可以反序列化,該屬性賦為默認值. public int eid; public void addressCheck() { System.out.println("Address check : " + name + " -- " + address); } }
序列化多個對象
注意: 序列化流一個文件只適合序列化一個對象(如果一個文件序列化多個對象, 會缺少標記)
-
操作步驟:
- 把序列化的多個對象,保存到一個集合對象(集合已經(jīng)實現(xiàn)了Serializable接口)
- 把這個集合作為對象,序列化到文件中(其實就是將集合容器作為對象序列化到文件中)
-
序列化多個對象代碼演示:
public class TestDemo { public static void main(String[] args) throws Exception { write(); read(); } public static void write() throws IOException { ArrayList<Dog> dogs = new ArrayList<>(); dogs.add(new Dog(23, "dahua")); dogs.add(new Dog(11, "erhua")); dogs.add(new Dog(55, "sanhua")); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dogs.txt")); oos.writeObject(dogs); oos.close(); } public static void read() throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dogs.txt")); Object o = ois.readObject(); //反序列化文件, 返回值是Object對象, 需要強轉(zhuǎn)成集合(泛型用父類多態(tài)接收) for (Object dog : (ArrayList<Object>)o) { System.out.println(dog); } ois.close(); } }
打印流(PrintStream)
打印流的介紹
System.out.println()
在控制臺打印輸出主胧,是調(diào)用print
方法和 println
方法完成的,這兩個方法都來自于java.io.PrintStream
類(成為打印流)习勤,該類能夠方便地打印各種數(shù)據(jù)類型的值(打印流中重寫了各種數(shù)據(jù)類型的print
和printlin
方法)踪栋,是一種便捷的輸出方式。
打印流的用法
-
構(gòu)造方法
public PrintStream(String fileName)
: 使用指定的文件名創(chuàng)建一個新的打印流图毕。public PrintStream(File file)
: 直接指定file對象public PrintStream(OutputStream out)
: 輸出流綁定的哪個對象, 就打印到哪個對象中 -
成員方法
public void print(各種數(shù)據(jù)類型);
public void println(各種數(shù)據(jù)類型);
-
打印流代碼演示
public static void main(String[] args) throws Exception{ PrintStream ps1 = new PrintStream("p.txt"); PrintStream ps2 = new PrintStream(new File("p1.txt")); PrintStream ps3 = new PrintStream(new FileOutputStream("p2.txt")); ps1.print("隨便寫各種類型數(shù)據(jù)"); }
-
修改系統(tǒng)打印流的流向
public static void main(String[] args) throws Exception{ PrintStream ps = new PrintStream("p.txt"); ps.print("更改打印"); System.out.println("JAVA"); //相當于修改了System靜態(tài)變量out的值 System.setOut(ps); System.out.println(); System.out.println("java更改"); }
裝飾設(shè)計模式
設(shè)計模式是指, 前輩們?yōu)榱私鉀Q一系列問題設(shè)計的方案
在我們今天所學(xué)的緩沖流中涉及到j(luò)ava的一種設(shè)計模式夷都,叫做裝飾模式.
裝飾設(shè)計模式概述(作用)
指在不改變原類, 不適用繼承的基礎(chǔ)上, 動態(tài)地擴展一個對象的功能.
裝飾設(shè)計模式的4個基本步驟
- 裝飾類(需要裝飾的新類)和被裝飾類(原類)必須實現(xiàn)相同的接口(可以將原類中的成員方法抽出來, 放在接口中)
- 在裝飾類中必須傳入被裝飾類的引用(就是在新類中定義裝飾類的成員變量對象)
- 在裝飾類中對需要擴展的方法進行擴展
- 在裝飾類中對不需要擴展的方法調(diào)用被裝飾類中的同名方法
裝飾設(shè)計模式代碼演示
-
先提供方法接口
public interface Star { public void sing(); public void dance(); }
-
讓原類去實現(xiàn)接口
public class LiuDeHua implements Star { @Override public void sing() { System.out.println("劉德華在唱忘情水..."); } @Override public void dance() { System.out.println("劉德華在跳街舞..."); } }
-
寫裝飾類,在裝飾類中擴展
/* 裝飾模式遵循原則: 裝飾類和被裝飾類必須實現(xiàn)相同的接口 在裝飾類中必須傳入被裝飾類的引用 在裝飾類中對需要擴展的方法進行擴展 在裝飾類中對不需要擴展的方法調(diào)用被裝飾類中的同名方法 */ public class LiuDeHuaWarpper implements Star { // 存放被裝飾類的引用 private LiuDeHua liuDeHua; // 通過構(gòu)造器傳入被裝飾類對象 public LiuDeHuaWarpper(LiuDeHua liuDeHua){ this.liuDeHua = liuDeHua; } @Override public void sing() { // 對需要擴展的方法進行擴展增強 System.out.println("劉德華在鳥巢的舞臺上演唱忘情水."); } @Override public void dance() { // 不需要增強的方法調(diào)用被裝飾類中的同名方法 liuDeHua.dance(); } }
commons-io工具包
commons-io工具包概述
commons-io是apache開源基金組織提供的一組有關(guān)IO操作的類庫,可以挺提高IO功能開發(fā)的效率予颤。commons-io工具包提供了很多有關(guān)io操作的類囤官,見下表:
包 | 功能描述 |
---|---|
org.apache.commons.io | 有關(guān)Streams冬阳、Readers、Writers治拿、Files的工具類 |
org.apache.commons.io.input | 輸入流相關(guān)的實現(xiàn)類摩泪,包含Reader和InputStream |
org.apache.commons.io.output | 輸出流相關(guān)的實現(xiàn)類,包含Writer和OutputStream |
org.apache.commons.io.serialization | 序列化相關(guān)的類 |
commons-io工具包 使用步驟
步驟:
- 下載commons-io相關(guān)jar包劫谅;http://commons.apache.org/proper/commons-io/
- 把commons-io-2.6.jar包復(fù)制到指定的Module的lib目錄中(必須在指定的Module的lib目錄下, lib目錄和src目錄為同級目錄)
- 將commons-io-2.6.jar加入到classpath中(IDEA中右鍵該工具包選擇Add as Libary表示添加到本模塊中作為工具庫)
commons-io工具包常用API
-
commons-io提供了一個工具類 org.apache.commons.io.IOUtils见坑,封裝了大量IO讀寫操作的代碼。其中有兩個常用方法:
- public static int copy(InputStream in, OutputStream out)捏检; 把input輸入流中的內(nèi)容拷貝到output輸
出流中荞驴,返回拷貝的字節(jié)個數(shù)(適合文件大小為2GB以下) - public static long copyLarge(InputStream in, OutputStream out);把input輸入流中的內(nèi)容拷貝到
output輸出流中贯城,返回拷貝的字節(jié)個數(shù)(適合文件大小為2GB以上)
代碼演示
public static void main(String[] args) throws Exception { // 文件路徑需要修改,改成自己文件的路徑 File file = new File("src/test.txt"); FileInputStream is = new FileInputStream(file); // 文件路徑需要修改 File file1 = new File("src/test1.txt"); FileOutputStream os = new FileOutputStream(file1); // 文件復(fù)制 IOUtils.copy(is, os); }
- public static int copy(InputStream in, OutputStream out)捏检; 把input輸入流中的內(nèi)容拷貝到output輸
-
commons-io還提供了一個工具類org.apache.commons.io.FileUtils熊楼,封裝了一些對文件操作的方法:
- public static void copyFileToDirectory(?nal File srcFile, ?nal File destFile) //復(fù)制文件到另外一個目錄
下。 - public static void copyDirectoryToDirectory( ?le1 , ?le2 );//復(fù)制?le1目錄到?le2位置能犯。
代碼演示
public static void main(String[] args) throws IOException { //1.將d:\\視頻.itcast文件復(fù)制到e:\\下 FileUtils.copyFileToDirectory(new File("d:\\視頻.itcast"), new File("e:\\")); //2.將"d:\\多級目錄"復(fù)制到"e:\\"下鲫骗。 FileUtils.copyDirectoryToDirectory(new File("d:\\多級目錄"), new File("e:\\")); }
- public static void copyFileToDirectory(?nal File srcFile, ?nal File destFile) //復(fù)制文件到另外一個目錄
今日小結(jié)
1.緩沖流【重點】
字節(jié)緩沖流(BufferedOutputStream和BufferedInputStream),沒有特有方法,性能比普通流更高字符緩沖流(BufferedWriter和BufferedReader),有特有方法,性能比普通流更高 BufferedWriter: public void newLine(); BufferedReader: public String readLine();
2.轉(zhuǎn)換流【重點】
轉(zhuǎn)換輸出流: 可以指定編碼寫文件
OutputStreamWriter
public OutputStreamWriter(OutputStream out,String 指定的編碼);
轉(zhuǎn)換輸入流: 可以指定編碼讀文件
InputStreamReader
public InputStreamReader(InputStream in,String 指定的編碼);3.序列化流【理解】
序列化流: 寫對象
ObjectOutputStream
public void writeObject(對象);//該對象的類必須實現(xiàn)java.io.Serializable接口
反序列化流: 讀對象
ObjectInputStream
public Object readObject();
4.打印流【理解】
PrintStream ps = new PrintStream(String path/File file/OutputStream out);
方法:
print(各種數(shù)據(jù)類型);
println(各種數(shù)據(jù)類型);5.裝飾設(shè)計模式【理解】
步驟:
a.被裝飾類和裝飾類實現(xiàn)同一個接口
b.裝飾類內(nèi)部必須含有被裝飾類的引用
c.在裝飾類中對需要裝飾的方法進行裝飾
d.在裝飾類中對不需要裝飾的方法調(diào)用原對象的方法6.commons-io【重點】
IOUtils 復(fù)制文件(2G以上和2G以下)
FileUtils 復(fù)制文件和復(fù)制文件夾