21.Java語言緩衝流、轉換流、序列化反序列化、更改列印流
緩衝流
緩衝流的基本原理,是在建立流物件時,會建立一個內建的預設大小的(8k)緩衝區陣列,通過緩衝區讀寫,減少系統IO次數,從而提高讀寫的效率。
1.位元組緩衝流:
1).輸出流:OutputStream
|--FileOutputStream(基本流)
|--FilterOutputStream
|--BufferedOutputStream(緩衝流)
2).輸入流:InputStream
|--FileInputStream(基本流)
|--FilterInputStream
|--BufferedInputStream(緩衝流)
3).構造方法:
BufferedInputStream(InputStream in) 建立一個 BufferedInputStream物件,引數是一個輸入流。InputStream是抽象
類,可以用子類物件
BufferedInputStream(Outputstream out) 建立一個 BufferedInputStream物件,引數是一個輸出流。Outputstream是抽
象類,可以用子類物件
4).程式碼示例:
BufferedInputStream bin = new BufferedInputStream(new FileInputStream("demo.txt"));
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("demo.txt"));
2.字元緩衝流:
1).輸出流:Writer
|--OutputStreamWriter(轉換流)
|--FileWriter(基本流)
|--BufferedWriter(緩衝流)
(特有方法:newLine():輸出一個換行符)
2).輸入流:Reader
|--InputStreamReader(轉換流)
|--FileReader(基本流)
|--BufferedReader(緩衝流)
(特有方法:readLine():讀取一行資料)轉換流
3).構造方法:
BufferedReader(Reader in) 建立使用預設大小的輸入緩衝區的 緩衝字元輸入流。
BufferedWriter(Writer out) 建立使用預設大小的輸出緩衝區的緩衝字元輸出流。
4).程式碼示例:
BufferedReader bin = new BufferedReader(new FileReader("demo.txt"));
BufferedWriter bout = new BufferedWriter(new FileWriter("demo.txt"));
3.緩衝流的使用_案例_文字排序:
public static void main(String[] args) throws IOException {
//建立輸入輸出的緩衝流
BufferedReader bin = new BufferedReader(new FileReader("sort.txt"));
BufferedWriter bout = new BufferedWriter(new
FileWriter("sort_allright.txt"));
//Map存放序號和對應的句子
Map<Integer,String> stringMap = new LinkedHashMap<>();
//用緩衝流的特有方法,一次讀寫一行
String s = null ;
while ((s = bin.readLine()) != null) {
//分割字串
String[] arr = s.split("\\.");
stringMap.put(Integer.parseInt(arr[0]), arr[1]);
}
//按照序號遍歷Map中的內容並寫出
for (int i = 1; i < stringMap.size(); i++) {
bout.write(i + "." + stringMap.get(i));
bout.newLine();
}
//關閉資源
bin.close();
bout.close();
}
轉換流
1.字元編碼和字符集:
字元編碼:
就是一套自然語言的字元與二進位制數之間的對應規則。
計算機是以二進位制儲存,按照某種規則,將字元儲存到計算機中,稱為編碼 。
將儲存在計算機中的二進位制數,按照某種規則解析顯示出來,稱為解碼
字符集:
常見的字符集(編碼表):記錄了字元和數字的對映關係。當計算機儲存“字元”時,實際儲存的是這個字元對應的數字的二進位制。
1.ASCII碼錶:最早的碼錶。記錄了128個字元,每個字元使用1個位元組表示。
2.中文的碼錶(GBxxxx)
1).GB2312:早期的碼錶,裡面一共記錄了7000多個漢字;現在已經不使用了。
2).GBK : 目前使用的碼錶。裡面一共記錄了2萬多個漢字,每個漢字使用2個位元組表示;
3).GB18030 : 未來要使用的碼錶。7萬多漢字。每個漢字使用1,2,3個位元組表示;
3.UTF-8碼錶:國際碼錶。有中文;字符采用1,2,3,4位元組表示。每個中文使用:3個位元組表示;
4.Unicode碼錶:國際碼錶,有中文(3,4千),每個字元使用2個位元組表示。Java就是支援Unicode碼錶的。
5.ISO-8859-1碼錶:沒有中文。
編碼引出的問題:
亂碼—解碼與編碼不一致
例如:Windows中文系統中就是使用的GBK的編碼,在IDEA中預設的字符集是UTF-8,兩種編碼中漢字佔用的位元組數不同,(UTF-8佔用三個位元組)讀取時就會出現亂碼 解決:讀取時將編碼轉換成一致
2.轉換輸出流和轉換輸入流:
1).轉換輸出流:
構造方法:
OutputStreamWriter(OutputStream in) : 建立一個用預設字符集的字元流。
OutputStreamWriter(OutputStream in, String charsetName) : 建立一個指定字符集的字元流。
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream("demo.txt"));
OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("demo.txt"),"GBK");
}
2).轉換輸入流:
構造方法:
InputStreamReader(InputStream in) : 建立一個使用預設字符集的字元流。
InputStreamReader(InputStream in, String charsetName) : 建立一個指定字符集的字元流。
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
InputStreamReader in1 = new InputStreamReader(new FileInputStream("demo.txt"));
InputStreamReader in2 = new InputStreamReader(new FileInputStream("demo.txt"),"GBk");
}
3.轉換輸入輸出流使用:
IDEA預設的字符集是UTF-8,Windows預設的是GBK,為了避免亂碼,使用GBK讀取文件,然後用UTF-8輸出
public static void main(String[] args) throws IOException {
//建立指定字符集轉換輸出輸入流,
InputStreamReader in = new InputStreamReader(
new FileInputStream("demo.txt"),"GBK");
OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream("demo_copy.txt"),"UTF-8");
//按照字元讀取
int b = 0;
while ((b = in.read()) != -1) {
out.write(b);
}
out.close();
in.close();
}
如果讀取的輸出的編碼不一致就會亂碼
序列化流
序列化:
指將一個“物件連同屬性值”一起儲存在一個檔案中,或者通過網路傳輸,這個過程叫:序列化。
反序列化;
指將之前序列化的物件,再次讀取到程式中,並在記憶體中建立物件。
1.序列化流ObjectOutputStream類;
構造方法:
public ObjectOutputStream(OutputStream out) : 建立一個指定OutputStream的ObjectOutputStream。
注意:被序列化的物件必須實現:java.io.Serializable(介面)
此介面無任何抽象方法,這種介面叫:標記介面,表示開啟了某些功能。
public static void main(String[] args) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_Student.txt"));
out.writeObject(new Student(1,"張三","男",23));
out.close();
}
2.反序列化ObjectInputStream類:
構造方法:
public ObjectInputStream(InputStream in) : 建立一個指定InputStream的ObjectInputStream。
注意:接收的Student必須是之前“序列化時”的那個包下的Student型別,不能是其它包下的,否則執行時異常。它必須是能夠找到class檔案的類
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_Student.txt"));
//返回Object型別
Student stu = (Student) in.readObject();
System.out.println(stu);
in.close();
}
3.版本號:
Serializable 介面給需要序列化的類,提供了一個序列版本號。 serialVersionUID 該版本號的目的在於驗證序列化的物件和對應類是否版本匹配。
例如:private static final long serialVersionUID = 2;
如果沒有給定序列號,如果修改了序列化的類,再次反序列化的時候(沒有再次序列化)就會拋異常,因為序列號不一樣了,如果給定了序列號,則不會拋異常
4.禁止屬性被序列化transient關鍵字
用transient關鍵字修飾屬性,在序列化時該甦醒不會被序列化
當一個屬性被transient修飾,反序列化出來的值時屬性的預設值
1 張三 男 0//年齡屬性被禁止序列化,輸出為0
5.序列化的使用_序列化集合:
public static void main(String[] args) throws IOException, ClassNotFoundException {
//建立序列化的集合並初始化資料
ArrayList<Student> stuList = new ArrayList<>();
stuList.add(new Student(1,"張三","男",19));
stuList.add(new Student(2,"張四","女",20));
stuList.add(new Student(3,"張五","男",21));
stuList.add(new Student(4,"張六","女",22));
//建立序列化輸出流和反序列化輸入流
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_xuliehuajihe.txt"));
ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_xuliehuajihe.txt"));
//序列化集合
out.writeObject(stuList);
//關閉資源
out.close();
//反序列化集合,並接受返回的集合
ArrayList<Student> studentList = (ArrayList<Student>) in.readObject();
//遍歷輸出反序列化返回的資料
for (Student student : studentList) {
System.out.println(student);
}
in.close();
}
列印流
1.位元組列印流PrintStream類
構造方法:
public PrintStream(String fileName) : 使用指定的檔名建立一個新的列印流。
2.改變列印流的方向:
System.out.println():向控制檯輸出資料,System.out就是:PrintStream型別;預設被指向:控制檯,想改變列印的方向,改變這個out就行
注意:
Out是System類的一個成員屬性,所以可以用get/set方法訪問
輸出方法和控制檯一樣
使用示例:
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("demo.txt");
System.setOut(ps);
System.out.println("呵呵");
}