緩衝流
緩衝流的基本原理,是在創建流對象時,會創建一個內置的默認大小的(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("呵呵");
}