JAVA從零開始學習知識整理——day10—【緩衝流、轉換流、序列化流】

一、緩衝流
1.1 概述
緩衝流,也叫高效流,是對4個基本的 FileXxx 流的增強,所以也是4個流,按照數據類型分類:
——字節緩衝流: BufferedInputStream , BufferedOutputStream
——字符緩衝流: BufferedReader , BufferedWriter
緩衝流的基本原理,是在創建流對象時,會創建一個內置的默認大小的緩衝區數組,通過緩衝區讀寫,減少系統IO次數,從而提高讀寫的效率。
創建格式:
——字節緩衝流

			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:\\a.txt"));
			//方法使用
			bos.write();  
   			BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\a.txt"));
   			bis.read()  

——字符緩衝流

		   BufferedReader bf =new BufferedReader(new FileReader("d:\\a.txt"));
		   bf.read();  
           BufferedWriter bw= new BufferedWriter(new FileWriter("d:\\a.txt"));
           bw.write();

練習-文本排序:
對亂序文本進行排序:

		public class BufferedTest {
				public static void main(String[] args) throws IOException {
				// 創建map集合,保存文本數據,鍵爲序號,值爲文字
				HashMap<String, String> lineMap = new HashMap<>();
				// 創建流對象
				BufferedReader br = new BufferedReader(new FileReader("in.txt"));
				BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
				// 讀取數據
				String line = null;
				while ((line = br.readLine())!=null) {
				// 解析文本
				String[] split = line.split("\\.");
				// 保存到集合
				lineMap.put(split[0],split[1]);
						}
			// 釋放資源
			br.close();
			// 遍歷map集合
			for (int i = 1; i <= lineMap.size(); i++) {
			String key = String.valueOf(i);
			// 獲取map中文本
			String value = lineMap.get(key);
			// 寫出拼接文本
			bw.write(key+"."+value);
			// 寫出換行
			bw.newLine();
		}
		// 釋放資源
		bw.close();
	}
}

二、轉換流

2.1 字符編碼和字符集
字符編碼計算機中儲存的信息都是用二進制數表示的,而我們在屏幕上看到的數字、英文、標點符號、漢字等字符是二進制數轉換之後的結果。按照某種規則,將字符存儲到計算機中,稱爲編碼 。反之,將存儲在計算機中的二進制數按照某種規則解析顯示出來,稱爲解碼 。比如說,按照A規則存儲,同樣按照A規則解析,那麼就能顯示正確的文本f符號。反之,按照A規則存儲,再按照B規則解析,就會導致亂碼現象。字符編碼Character Encoding : 就是一套自然語言的字符與二進制數之間的對應規則
——ASCII字符集 :
ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼)是基於拉丁
字母的一套電腦編碼系統,用於顯示現代英語,主要包括控制字符(回車鍵、退格、換行鍵等)和可顯
示字符(英文大小寫字符、阿拉伯數字和西文符號)。基本的ASCII字符集,使用7位(bits)表示一個字符,共128字符。ASCII的擴展字符集使用8位(bits)表示一個字符,共256字符,方便支持歐洲常用字符。
——ISO-8859-1字符集:
拉丁碼錶,別名Latin-1,用於顯示歐洲使用的語言,包括荷蘭、丹麥、德語、意大利語、西班牙語等。ISO-5559-1使用單字節編碼,兼容ASCII編碼。
——GBxxx字符集:
GB就是國標的意思,是爲了顯示中文而設計的一套字符集。
GB2312:簡體中文碼錶。一個小於127的字符的意義與原來相同。但兩個大於127的字符連在一起時,
就表示一個漢字,這樣大約可以組合了包含7000多個簡體漢字,此外數學符號、羅馬希臘的字母、日文
的假名們都編進去了,連在ASCII裏本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這
就是常說的"全角"字符,而原來在127號以下的那些就叫"半角"字符了。
GBK:最常用的中文碼錶。是在GB2312標準基礎上的擴展規範,使用了雙字節編碼方案,共收錄了
21003個漢字,完全兼容GB2312標準,同時支持繁體漢字以及日韓漢字等。
GB18030:最新的中文碼錶。收錄漢字70244個,採用多字節編碼,每個字可以由1個、2個或4個字節
組成。支持中國國內少數民族的文字,同時支持繁體漢字以及日韓漢字等。
——Unicode字符集 :
Unicode編碼系統爲表達任意語言的任意字符而設計,是業界的一種標準,也稱爲統一碼、標準萬國碼。它最多使用4個字節的數字來表達每個字母、符號,或者文字。有三種編碼方案,UTF-8、UTF-16和UTF32。最爲常用的UTF-8編碼。UTF-8編碼,可以用來表示Unicode標準中任何字符,它是電子郵件、網頁及其他存儲或傳送文字的應用中,優先採用的編碼。互聯網工程工作小組(IETF)要求所有互聯網協議都必須支持UTF-8編碼。所以,我們開發Web應用,也要使用UTF-8編碼。它使用一至四個字節爲每個字符編碼,編碼規則:

  1. 128個US-ASCII字符,只需一個字節編碼。
  2. 拉丁文等字符,需要二個字節編碼。
  3. 大部分常用字(含中文),使用三個字節編碼。
  4. 其他極少使用的Unicode輔助字符,使用四字節編碼。

2.2 編碼出現的問題
在IDEA中,使用 FileReader 讀取項目中的文本文件。由於IDEA的設置,都是默認的 UTF-8 編碼,所以沒有任何問題。但是,當讀取Windows系統中創建的文本文件時,由於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();
		}
}
輸出結果

2.3 InputStreamReader、

//默認格式讀取(UTF-8)
        InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\a.txt"));
        isr.read();
        //以指定的編碼啊格式讀取
        InputStreamReader isr1 = new InputStreamReader(new FileInputStream("D:\\a.txt"),"GBK");
        isr1.read();

2.4 OutputStreamWriter

 //默認格式寫入(UTF-8)
        OutputStreamWriter osw =new OutputStreamWriter(new FileOutputStream("D:\\a.txt"));
        osw.write();
        //以指定編碼格式寫入
        OutputStreamWriter osw1 =new OutputStreamWriter(new FileOutputStream("D:\\a.txt"),"UTF-8");
        osw.write();

三、序列化
3.1 概述
Java 提供了一種對象序列化的機制。用一個字節序列可以表示一個對象,該字節序列包含該 對象的數據 、 對象的類型 和 對象中存儲的屬性 等信息。字節序列寫出到文件之後,相當於文件中持久保存了一個對象的信息。
反之,該字節序列還可以從文件中讀取回來,重構對象,對它進行反序列化。 對象的數據 、 對象的類型 和 對象中存儲的數據 信息,都可以用來在內存中創建對象。
3.2 ObjectOutputStream類
——public ObjectOutputStream(OutputStream out) : 創建一個指定OutputStream的ObjectOutputStream。
序列化操作

  1. 一個對象要想序列化,必須滿足兩個條件:
    該類必須實現 java.io.Serializable 接口, Serializable 是一個標記接口,不實現此接口的類將不會使任
    何狀態序列化或反序列化,會拋出 NotSerializableException 。
    該類的所有屬性必須是可序列化的。如果有一個屬性不需要可序列化的,則該屬性必須註明是瞬態的,使用
    transient 關鍵字修飾。
	public class Employee *implements java.io.Serializable* {
		public String name;
		public String address;
		public transient int age; // transient瞬態修飾成員,不會被序列化
		public void addressCheck() {
			System.out.println("Address check : " + name + " ‐‐ " + address);
	}
}

寫出對象:

			public class SerializeDemo{
					public static void main(String [] args) {
							Employee e = new Employee();
							e.name = "zhangsan";
							e.address = "beiqinglu";
							e.age = 20;
							try {
									// 創建序列化流對象
							ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.txt"));
									// 寫出對象
							out.writeObject(e);
									// 釋放資源
							out.close();
							fileOut.close();
								System.out.println("Serialized data is saved"); // 姓名,地址被序列化,年齡沒有被序列化。
							} catch(IOException i) {
									i.printStackTrace();
							}
			}
}
輸出結果:
Serialized data is saved

3.3 ObjectInputStream類
反序列化操作:
如果能找到一個對象的class文件,我們可以進行反序列化操作,調用 ObjectInputStream 讀取對象的方法:public final Object readObject () : 讀取一個對象。

		public class DeserializeDemo {
				public static void main(String [] args) {
						Employee e = null;
						try {
							// 創建反序列化流
						FileInputStream fileIn = new FileInputStream("employee.txt");
						ObjectInputStream in = new ObjectInputStream(fileIn);
						// 讀取一個對象
						e = (Employee) in.readObject();
						// 釋放資源
						in.close();
						fileIn.close();
						}catch(IOException i) {
						// 捕獲其他異常
							i.printStackTrace();
							return;
						}catch(ClassNotFoundException c) {
						// 捕獲類找不到異常
						System.out.println("Employee class not found");
						c.printStackTrace();
						return;
				}
					// 無異常,直接打印輸出
					System.out.println("Name: " + e.name); // zhangsan
					System.out.println("Address: " + e.address); // beiqinglu
					System.out.println("age: " + e.age); // 0
		}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章