之前學習了基本的一些流,作爲IO流的入門,我們要見識一些更強大的流。比如能夠高效讀寫的緩衝流,能夠轉換編碼的轉換流,能夠持久化存儲對象的序列化流等等。這些功能更爲強大的流,都是在基本的流對象基礎之上創建而來的,就像穿上鎧甲的武士一樣,相當於是對基本流對象的一種增強。
1.概述
緩衝流,也叫高效流,是對4個基本的FileXxx
流的增強,所以也是4個流,按照數據類型分類:
- 字節緩衝流:
BufferedInputStream
,BufferedOutputStream
- 字符緩衝流:
BufferedReader
,BufferedWriter
緩衝流的基本原理,是在創建流對象時,會創建一個內置的默認大小的緩衝區數組,通過緩衝區讀寫,減少系統IO次數,從而提高讀寫的效率。
2. 字節緩衝流
構造方法
public BufferedInputStream(InputStream in)
:創建一個 新的緩衝輸入流。public BufferedOutputStream(OutputStream out)
: 創建一個新的緩衝輸出流。
構造舉例,代碼如下:
// 創建字節緩衝輸入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 創建字節緩衝輸出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
效率測試
查詢API,緩衝流讀寫方法與基本的流是一致的,我們通過複製大文件(375MB),測試它的效率。
- 基本流,代碼如下:
public class BufferedDemo {
public static void main(String[] args) throws FileNotFoundException {
// 記錄開始時間
long start = System.currentTimeMillis();
// 創建流對象
try (
FileInputStream fis = new FileInputStream("JDK8.zip");
FileOutputStream fos = new FileOutputStream("copy.zip")
){
// 讀寫數據
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
// 記錄結束時間
long end = System.currentTimeMillis();
System.out.println("普通流複製時間:"+(end - start)+" 毫秒");
}
}
- 緩衝流,代碼如下:
public class BufferedDemo {
public static void main(String[] args) throws FileNotFoundException {
// 記錄開始時間
long start = System.currentTimeMillis();
// 創建流對象
try (
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("JDK8.zip"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.zip"));
){
// 讀寫數據
int b;
while ((b = bis.read()) != -1) {
bos.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
// 記錄結束時間
long end = System.currentTimeMillis();
System.out.println("緩衝流複製時間:"+(end - start)+" 毫秒");
}
}
不帶緩衝的流的工作原理:它讀取到一個字節/字符,就向用戶指定的路徑寫出去來 讀一個寫一個 所以就慢了
帶緩衝的流的工作原理:讀取到一個字節/字符,先不輸出,等源湊足了緩衝的最大容量後一次性寫出去,從而提高了工作效率
舉個現實生活中的例知子:假設你是一個快遞員,不帶緩衝的流就像快遞公司給你一份快遞你就跑一次,而帶緩衝的流就像快遞公司給你一份快遞,你先不去,等攢攢多道一起送,試想一下,是不是效率提高了?
如何更快呢?
使用數組的方式,代碼如下:
public class BufferedDemo {
public static void main(String[] args) throws FileNotFoundException {
// 記錄開始時間
long start = System.currentTimeMillis();
// 創建流對象
try (
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("JDK8.zip"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.zip"));
){
// 讀寫數據
int len;
byte[] bytes = new byte[8*1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0 , len);
}
} catch (IOException e) {
e.printStackTrace();
}
// 記錄結束時間
long end = System.currentTimeMillis();
System.out.println("緩衝流使用數組複製時間:"+(end - start)+" 毫秒");
}
}
3.字符緩衝流
構造方法
public BufferedReader(Reader in)
:創建一個 新的緩衝輸入流。public BufferedWriter(Writer out)
: 創建一個新的緩衝輸出流。
構造舉例,代碼如下:
// 創建字符緩衝輸入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 創建字符緩衝輸出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
特有方法
字符緩衝流的基本方法與普通字符流調用方式一致,不再闡述,我們來看它們具備的特有方法。
- BufferedReader:
public String readLine()
: 讀一行文字。 - BufferedWriter:
public void newLine()
: 寫一行行分隔符,由系統屬性定義符號。
readLine
方法演示,代碼如下:
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
// 創建流對象
BufferedReader br = new BufferedReader(new FileReader("in.txt"));
// 定義字符串,保存讀取的一行文字
String line = null;
// 循環讀取,讀取到最後返回null
while ((line = br.readLine())!=null) {
System.out.print(line);
System.out.println("------");
}
// 釋放資源
br.close();
}
}
newLine
方法演示,代碼如下:
public class BufferedWriterDemo throws IOException {
public static void main(String[] args) throws IOException {
// 創建流對象
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
// 寫出數據
bw.write("我是");
// 寫出換行
bw.newLine();
bw.write("一個");
bw.newLine();
bw.write("男人");
bw.newLine();
// 釋放資源
bw.close();
}
}
輸出效果:
我是
一個
男人