Java基礎進階 緩衝流、轉換流、序列化流、Files類
01.第一章:緩衝流_概述
1).我們之前使用字節/字符的基本流時,使用數組的方式比較快。
2).基於這種原因,Java類庫中提供了一種“緩衝流”類,它們內部自動帶了“數組”,而且自動向數組中讀、寫數據,
這種流:叫:緩衝流。由於它內部帶了數組,所以可以大大提高程序的讀寫效率。它們內部的“數組”就叫:緩存區。
3).緩衝流的類結構:
A).字節流:
1).輸出流:OutputStream(三種輸出的方法)
|–FileOutputStream(基本流)
|–FilterOutputStream(不學)
|–BufferedOutputStream(緩衝流–今天學)
2).輸入流:InputStream(兩種讀取的方法)
|–FileInputStream(基本流)
|–FilterInputStream(不學)
|–BufferedInputStream("緩衝流–今天學)
B).字符流:
1).輸出流:Writer(五種輸出的方法)
|–OutputStreamWriter(轉換流–今天學)
|–FileWriter(基本流)
|–BufferedWriter(緩衝流–今天學)
2).輸入流:Reader(兩種讀取的方法)
|–InputStreamReader(轉換流–今天學)
|–FileReader(基本流)
|–BufferedReader(緩衝流–今天學)
注意:
1).緩衝流的前綴都帶:Buffered
2).緩衝流基本沒有特有方法,都是從父類繼承/重寫的。只是他們內部的工作方式不同,可以提供”緩存區”
來提高程序的讀寫效率。
02.第一章:緩衝流_字節緩衝流
1).輸出流:BufferedOutputStream
2).輸入流:BufferedInputStream
無特有方法,跟基本流一樣操作,就是:效率高。
public class Demo {
public static void main(String[] args) {
long start = System.currentTimeMillis();
// copy1();//3509 毫秒(緩衝流--一次讀寫一個字節)
// copy2();//280 毫秒(緩衝流--一次讀寫一個字節數組)
// copy3();//361061 毫秒(基本流--一次讀寫一個字節)
copy4();//875 毫秒(基本流--一次讀寫一個字節數組)
long end = System.currentTimeMillis();
System.out.println("用時:" + (end - start) + " 毫秒");
}
private static void copy4() {
try (FileInputStream in = new FileInputStream("d:\\視頻.itcast");
FileOutputStream out = new FileOutputStream("d:\\視頻_copy3.itcast")
) {
//一次讀寫一個字節數組
int len = 0;
byte[] byteArray = new byte[1024];
while ((len = in.read(byteArray)) != -1) {
out.write(byteArray,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copy3() {
try (FileInputStream in = new FileInputStream("d:\\視頻.itcast");
FileOutputStream out = new FileOutputStream("d:\\視頻_copy3.itcast")
) {
//一次讀寫一個字節
int b = 0;
while ((b = in.read()) != -1) {
out.write(b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copy2() {
//1.構造一個輸入流
try (BufferedInputStream bufIn = new BufferedInputStream(
new FileInputStream("d:\\視頻.itcast"));
BufferedOutputStream bufOut = new BufferedOutputStream(
new FileOutputStream("d:\\視頻_copy2.itcast"))
) {
//一次讀寫一個字節數組
int len = 0;
byte[] byteArray = new byte[1024];
while ((len = bufIn.read(byteArray)) != -1) {
bufOut.write(byteArray,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copy1() {
//1.構造一個輸入流
try (BufferedInputStream bufIn = new BufferedInputStream(
new FileInputStream("d:\\視頻.itcast"));
BufferedOutputStream bufOut = new BufferedOutputStream(
new FileOutputStream("d:\\視頻_copy1.itcast"))
) {
//一次讀寫一個字節
int b = 0;
while ((b = bufIn.read()) != -1) {
bufOut.write(b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
03.第一章:緩衝流_字符緩衝流
1).輸出流:BufferedWriter
特有方法:newLine():輸出一個換行符“\r\n”;
2).輸入流:BufferedReader
特有方法:readLine():讀取一行數據。
3).示例代碼:
public class Demo {
public static void main(String[] args) {
//1.字符緩衝輸入流
try (BufferedReader bufIn = new BufferedReader(
new FileReader("d:\\demo01.txt"));
BufferedWriter bufOut = new BufferedWriter(
new FileWriter("d:\\demo01_copy.txt"))
) {
//一次讀一行
String row = null;
while((row = bufIn.readLine()) != null){//注意:讀取一行,不包括換行符
bufOut.write(row);
bufOut.newLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
04.第一章:緩衝流_練習_文本排序_案例分析
05.第一章:緩衝流_練習_文本排序_案例實現
public class Demo {
public static void main(String[] args) {
//1.構造一個輸入流--按行讀--字符緩衝輸入流
try (BufferedReader bufIn = new BufferedReader(new FileReader("demo01.txt"));
BufferedWriter bufOut = new BufferedWriter(new FileWriter("demo01_copy.txt"))
) {
//一次讀寫一行
String row = null;
Map<Integer, String> map = new HashMap<>();
while ((row = bufIn.readLine()) != null) {//row = 3.xxxxxx
String id = row.substring(0, row.indexOf("."));
String str = row.substring(row.indexOf(".") + 1);
map.put(Integer.parseInt(id), str);
}
//循環寫入
for (int i = 1; i <=9 ; i++) {
String str = map.get(i);//xxxxx
str = i + "." + str;//1.xxxxx
bufOut.write(str);
bufOut.newLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
06.第二章:轉換流_編碼引出的問題
1).如果磁盤上有一個GBK編碼的文件,我們使用程序用UTF-8編碼讀取,這樣就會產生:亂碼的現象。
2).FileWriter和FileReader不能指定編碼方式,固定用系統默認的(UTF-8)讀取,很不靈活。
3).它們的父類提供了指定編碼的方式:
Writer
|–OutputStreamWriter(轉換流)(可以指定字符集)
|–FileWriter(子類)(只能使用系統默認字符集)
Reader
|–InputStreamReader(轉換流)(可以指定字符集)
|–FileReader(子類)(只能使用系統默認字符集)
07.第二章:轉換流_轉換輸出流OutputStreamWriter的使用
public class Demo {
public static void main(String[] args) {
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("demo04.txt"),"GBK")) {
osw.write("你好");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
08.第二章:轉換流_轉換輸入流InputStreamReader的使用
public class Demo {
public static void main(String[] args) {
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("demo04.txt"),"GBK")) {
int c = 0;
while ((c = isr.read()) != -1) {
System.out.println((char)c);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
09.第二章:轉換流_練習_轉換文件編碼
1).複製一個GBK的文件,新文件要求是:UTF-8編碼的。
2).代碼:
public class Demo {
public static void main(String[] args) {
//1.構造一個輸入流--由於要指定GBK讀取,所以使用:轉換流
//2.構造一個輸出流,使用UTF-8編碼
try (InputStreamReader in = new InputStreamReader(
new FileInputStream("demo05.txt"),"GBK");
OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream("demo05_UTF8.txt"),"UTF-8")
) {
//一次讀取一個字符
int c = 0;
while ((c = in.read()) != -1) {//按GBK讀取的
out.write(c);//按UTF-8輸出
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
10.第三章:序列化_概述:
1).什麼是“序列化”:指將一個內存中的“對象”,連同“屬性值”一起存儲到文件中。
2).什麼是“反序列化”:指將之前序列化的對象,從文件中再讀取進來,並在內存中再次創建對象。
11.第三章:序列化_序列化流ObjectOutputStream類
public class Student implements Serializable{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo {
public static void main(String[] args) {
//創建一個序列化流對象
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("demo07_obj.txt"))) {
Student stu = new Student("成龍", 17);
//序列化對象
oos.writeObject(stu);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
12.第三章:序列化_反序列化ObjectInputStream類
public class Demo {
public static void main(String[] args) {
//1.創建一個反序列化對象
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("demo07_obj.txt"))) {
//讀取對象
Object obj = ois.readObject();//在內存中創建一個Student對象
//強轉
Student stu = (Student)obj;
System.out.println(stu);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
13.第三章:序列化_關於版本號
public class Student implements Serializable{
public String name;
public int age;
private static final long serialVersionUID = 2L;
}
14.第三章:序列化_禁止屬性被序列化transient關鍵字
1).如果類中的某個屬性不希望被序列化,可以被聲明爲:transient
2).示例:
public class Student implements Serializable{
public String name;
public transient int age;//當序列化Student對象時,此屬性的值不會被序列化到文件中
}
15.第三章:序列化_練習_序列化集合
1).不建議一個文件中序列化多個對象。可以將多個對象存儲到一個List集合中,然後將這個集合對象序列化到文件中。
2).序列化:
public class Demo {
public static void main(String[] args) {
Student stu1 = new Student("成龍", 17);
Student stu2 = new Student("甄子丹", 15);
Student stu3 = new Student("洪金寶", 19);
ArrayList<Student> stuList = new ArrayList<>();
stuList.add(stu1);
stuList.add(stu2);
stuList.add(stu3);
//序列化
try (ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("demo10_obj.txt"))) {
//序列化集合
out.writeObject(stuList);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3).反序列化:
public class Demo02 {
public static void main(String[] args) {
try (ObjectInputStream objIn = new ObjectInputStream(
new FileInputStream("demo10_obj.txt"))) {
//反序列化
Object obj = objIn.readObject();
List<Student> stuList = (List<Student>)obj;
//驗證
for (Student stu : stuList) {
System.out.println(stu);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
16.第四章:打印流_概述
1).打印流:
1).字節打印流:PrintStream
2).字符打印流:PrintWriter
2).特點:
1).只有輸出流,沒有輸入流;
2).可以向控制檯打印,也可以向文件中打印
17.第四章:打印流_字節打印流PrintStream類
public class Demo {
public static void main(String[] args) {
PrintStream ps = System.out;
ps.println("HelloWorld!");
//改變它的方向
try (PrintStream ps2 = new PrintStream("demo11.txt")) {
//將ps2賦值到System中,代替之前的out
System.setOut(ps2);
//再打印
System.out.println("我愛");
System.out.println("Java");
System.out.println("呵呵");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
=============================================================
學習目標總結:
01.能夠使用字節緩衝流讀取數據到程序
02.能夠使用字節緩衝流寫出數據到文件
03.能夠明確字符緩衝流的作用和基本用法
04.能夠使用緩衝流的特殊功能
05.能夠闡述編碼表的意義
1).編碼表中存儲的各國的“文字”和“十進制數字”的映射關係。目的存儲這個文字時,
要存儲它對應的十進制的二進制表示方式。
ASCII:a --> 97 --> 計算機:97的二進制
b --> 98 --> 計算機:98的二進制
GBK:"你" --> 50403 --> 計算機:50403的二進制
06.能夠使用轉換流讀取指定編碼的文本文件
07.能夠使用轉換流寫入指定編碼的文本文件
08.能夠使用序列化流寫出對象到文件
09.能夠使用反序列化流讀取文件到程序中