一、基本介紹:
1、節點流可以從一個特定的數據源讀寫數據,如FileReader、 FileWriter
如圖:字節流是直接對數據源(文件,數組之類存放數據的地方)進行操作
2.處理流(也叫包裝流)是"連接"在已存在的流(節 點流或處理流)之上,為程序提供
更為強大的讀寫功能,也更加靈活,如BufferedReader、BufferedWriter
3、節點流和處理流的區別和聯系:
1).節點流是底層流/低級流,直接跟數據源相接。
2).處理流(包裝流)包裝節點流,既可以消除不同節點流的實現差異,也可以提供更方便的方法
來完成輸入輸出。
3).處理流(也叫包裝流)對節點流進行包裝,使用了修飾器設計模式,不會直接與數據
源相連[模擬修飾器設計模式]
●處理流的功能主要體現在以下兩個方面:
1.性能的提高:主要以增加緩沖的方式來提高輸入輸出的效率。
2.操作的便捷:處理流可能提供了-系列便捷的方法來一次輸入輸出大批量的數據, 使
用更加靈活方便
二、處理流-BufferedReader和BufferedWriter的使用
簡介:BufferedReader和BufferedWriter屬於字符流,是按照字符來讀取數據的
關閉時,只需要關閉外層流即可[可以調試看源碼:在底層會用close()關閉Reader]
注意:BufferedReader和BufferedWriter是安裝字符操作,不能操作二進制文件
常見的二進制文件【聲音,視頻,doc,pdf,圖片】
處理流的兩個實例:
BufferedReader
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class BufferReader_ { public static void main(String[] args) throws IOException { //創建一個文件對象 String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\news3.txt"; String line = null; //創建一個 BufferedReader的對象,並包裝一個FileReader在里面 BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath1)); while ((line = bufferedReader.readLine()) != null) {//readline表示讀取一行的字符串 System.out.println(line); } //關閉BufferedReader處理流,只需要關閉外層即可,內層的FileReader會在底層自動關閉 bufferedReader.close(); } }
BufferedWriter
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class BufferWeriter_ { public static void main(String[] args) throws IOException { //定義文件路徑 String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\news1.txt"; //創建一個BufferWriter對象 // BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath1));//直接覆蓋原來內容 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath1,true));//在原來的內容上添加,添加到文章內容之后 bufferedWriter.write("這里水太深你把握不住2.0。"); bufferedWriter.newLine();//插入一個換行符 bufferedWriter.write("這里水太深你把握不住3.0。"); bufferedWriter.close(); } }
三、處理流:BufferedInputStream和BufferedOutputStream
1、BufferedInputStream:BufferedInputStream是字節流在創建BufferedInputStream
時,會創建一個內部緩沖區數組.
繼承實現圖
2、BufferedOutputStream:BufferedOutputStream是字節流,實現緩沖的輸出流,可以將多個字節寫入底層輸出流中,而不必對每次字節寫入調用底層系統
繼承實現圖
使用BufferedInputStream和BufferedOutputStream2完成二進制文件的拷貝:
import java.io.*; public class BufferedCopy { public static void main(String[] args) throws IOException { //復制的源地址和目的地址 String srcPath = "C:\\Users\\wenman\\Desktop\\imageTest\\test33.jpg"; String destPath = "C:\\Users\\wenman\\Desktop\\imageTest\\test11.jpg"; //定義一個用於接收文件的byte[]數組和記錄數據大小的整數 byte[] bytes = new byte[100]; int dataLine = 0; //創建Buffered BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcPath)); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destPath)); while ((dataLine=bufferedInputStream.read(bytes))!= -1){ bufferedOutputStream.write(bytes, 0, dataLine); } bufferedInputStream.close(); bufferedOutputStream.close(); } }
四。對象流-ObjectlnputStream和objectOutputStream
➢序列化和反序列化
1.序列化就是在保存數據時,保存數據的值和數據類型
2.反序列化就是在恢復數據時,恢復數據的值和數據類型
3.需要讓某個對象支持序列化機制,則必須讓其類是可序列化的,為了讓某個類是可序列化的,該
類必須實現如下兩個接口之- -:
➢Serializable//這是一個標記接口,沒有方法
➢Externalizable //該接口有方法需要實現,因此我們一般實現上面的Serializable接口
序列化反序列化類比圖如下:
1、ObjectlnputStream和objectOutputStream基本介紹:
1).功能:提供了對基本類型或對象類型的序列化和反序列化的方法
2). ObjectOutputStream 提供序列化功能
3). ObjectlnputStream 提供反序列化功能
ObjectlnputStream的實現繼承圖:
objectOutputStream的實現繼承圖:
代碼實例:objectOutputStream
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class ObjectOutput { public static void main(String[] args) throws IOException { //定義輸出的文件地址 String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\data.dat"; //定義一個ObjectOutputStream對象,並包裝FileOutputStream的類 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath1)); objectOutputStream.writeInt(100); objectOutputStream.writeDouble(12.5); objectOutputStream.writeChar('A'); objectOutputStream.writeObject(new Dog("zhangsan", 20)); objectOutputStream.close(); } }
代碼實例:ObjectlnputStream
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class ObjectInput { public static void main(String[] args) throws IOException, ClassNotFoundException { //文件路徑 String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\data.dat"; ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(filePath1)); //讀取文件中存在的內容(內容讀取時,應當按照存放時的順序讀取文件) System.out.println(inputStream.readInt()); System.out.println(inputStream.readDouble()); System.out.println(inputStream.readChar()); //其中,Object的類型,應該是在整個包中可以訪問的,因為數據在存進文件時,類型所在的包也是保存進文件的 //所以在反序列化的時候,又會按照所記錄的包的類型去加載,包找不到就會加載錯誤,反序列化失敗 Object dog = inputStream.readObject(); System.out.println(dog); // Dog dog1 = (Dog) dog; // System.out.println(dog1.getName() + "----" + dog1.getAge()); inputStream.close(); } }
2、注意事項和細節說明
1)讀寫順序要一致
2)要求序列化或反序列化對象,需要實現 Serializable
3)序列化的類中建議添加SerialVersionUID,為了提高版本的兼容性
4)序列化對象時,默認將里面所有屬性都進行序列化,但除了static(靜態)或transient(臨時)修飾的成員5)序列化對象時,要求里面屬性的類型也需要實現序列化接口
6)序列化具備可繼承性,也就是如果某類已經實現了序列化,則它的所有子類也已經默認實現了序列化
標准輸入和標准輸出的編譯類型和運行類型:
五、轉換流-lnputStreamReader和 OutputStreamWriter
1. InputStreamReader:Reader的子類,可以將InputStream(字節流)包裝成Reader(字符流)
指定文件讀取時的編碼:繼承實現圖
2.OutputStreamWriter:Writer的子類,實現將OutputStream(字節流)
指定文件讀取時的編碼:繼承實現圖
包裝成Writer(字符流)
3.當處理純文本數據時,如果使用字符流效率更高,並且可以有效解決中文
問題,所以建議將字節流轉換成字符流
4.可以在使用時指定編碼格式(比如utf-8, gbk , gb2312, ISO8859-1等)
引出問題:當文件中的編碼和讀取的編碼時出現亂碼問題:
@Test public void Read1() throws IOException { String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\news1.txt"; byte[] bytes = new byte[100]; int dataLine = 0; FileInputStream fileInputStream = new FileInputStream(filePath1); while ((dataLine = fileInputStream.read(bytes)) != -1){ System.out.println(new String(bytes,0,dataLine)); } fileInputStream.close(); }
原文:這里水太深你把握不住。這里水太深你把握不住2.0。這里水太深你把握不住2.0。
這里水太深你把握不住3.0。
讀取后的內容:
解決問題:
import org.junit.jupiter.api.Test; import java.io.*; public class BufferedReaderUtf { public static void main(String[] args) { String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\news1.txt"; } @Test public void Read1() throws IOException { String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\news1.txt"; byte[] bytes = new byte[100]; int dataLine = 0; FileInputStream fileInputStream = new FileInputStream(filePath1); while ((dataLine = fileInputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, dataLine)); } fileInputStream.close(); } @Test public void Read2() throws IOException { //文件路徑 String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\news1.txt"; //給字節流設置一個讀取的編碼格式(在字節流中定義了一個新的流對象),指定編碼gbk InputStreamReader streamReader = new InputStreamReader(new FileInputStream(filePath1), "gbk"); //用一個處理流包裝字節流 BufferedReader bufferedReader = new BufferedReader(streamReader);
//可以將上述兩行轉換為一行減少冗余
// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath1)));
String data = null; //獲取文件內容輸出 while ((data = bufferedReader.readLine()) != null) { System.out.println(data); } bufferedReader.close();//關閉處理流,只需要關閉外層的,內層的會自動關閉 } }
結果:
OutputStreamWriter的使用:
import java.io.*; public class BufferedWriterUtf { public static void main(String[] args) throws IOException { //文件路徑 String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\news2.txt"; String test = "這個世界上有很多"; //將一個輸出流轉換為一個字節轉換流,用一個處理流包裝起來,設置編碼方式為gbk,表示該文件內容為gbk BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath1),"gbk")); //輸出字符到指定文件 bufferedWriter.write(test); //輸出一個換行符 bufferedWriter.newLine(); //關閉外層處理流,內層字節流會自己關閉 bufferedWriter.close(); } }
六、打印流:-PrintStream和PrintWriter:打印流只有輸出流,沒有輸入流
PrintStream的繼承實現圖
PrintWriter的實現繼承圖
代碼實例:
import org.junit.jupiter.api.Test; import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; public class Print { @Test public void printStream_() throws IOException { String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\note.txt"; PrintStream out = System.out; //在默認情況下就輸出到控制台 out.println("hello"); //因為println在底層使用的是write,所有可以直接使用Write輸出 out.write("hello".getBytes()); System.setOut(new PrintStream(filePath1)); System.out.println("hello,little"); } @Test public void printWrite_() throws IOException { String filePath1 = "C:\\Users\\wenman\\Desktop\\test\\note.txt"; PrintWriter printWriter = new PrintWriter(new FileWriter(filePath1));//輸出到文件 // PrintWriter printWriter = new PrintWriter(System.out);//輸出到控制台 printWriter.print("ghellouhadkuah"); printWriter.close(); } }
七、Properties類
基本介紹:
1)專門用於讀寫配置文件的集合類
配置文件的格式:
鍵=值
鍵=值
2)注意:鍵值對不需要有空格,值不需要用引號一起來。默認類型是String
3) Properties的常見方法
ldad: 加載配置文件的鍵值對到Properties對象·
list:將數據顯示到指定設備
getProperty(key):根據鍵獲取值
setProperty(key,value):設置鍵值對到Properties對象
store:將Properties中的鍵值對存儲到配置文件,在idea中,保存信息到配置文件,如果含有中文,會存儲為unicode碼
http://tool.chinaz.com/tools/unicode.aspx unicode碼查詢工具