JavaIO流03 4.常用的類02 4.4節點流和處理流 4.4.1基本介紹 節點流可以從一個特定的數據源讀寫數據,如FileReader、FileWriter 數據源就是存放數據的地方,比如文件、數組、字元串、管道等 處理流(也叫包裝流)是“連接”在已經存在的流(節點流或者處理流)之上,為程式提 ...
JavaIO流03
4.常用的類02
4.4節點流和處理流
4.4.1基本介紹
-
節點流可以從一個特定的數據源讀寫數據,如FileReader、FileWriter
數據源就是存放數據的地方,比如文件、數組、字元串、管道等
- 處理流(也叫包裝流)是“連接”在已經存在的流(節點流或者處理流)之上,為程式提供更為強大的讀寫功能,也更加靈活,如BufferedReader、BufferedWriter
- 節點流和處理流的區別和聯繫:
- 節點流是底層流(低級流),直接和數據源相連接。
- 處理流(包裝流)對節點流進行了包裝,既可以消除不同節點流的實現差異,也可以提供更方便的方法來完成輸入輸出。
- 處理流對節點流進行了包裝,使用了修飾器的設計模式,不會直接與數據源相連接。
-
處理流特點:
1.性能的提高:主要以增加緩衝的方式來提高輸入輸出的效率。
2.操作的便捷:處理流提供了一系列便捷的方法來一次輸入輸出大批量的數據,使用更加靈活方便。
4.4.2模擬包裝流-修飾器模式
Reader_:
package li.io;
/**
* 模擬包裝流的修飾器模式
*/
public abstract class Reader_ {//抽象類
public void readFile() {}
public void readString() {}
}
FileReader_:
package li.io;
public class FileReader_ extends Reader_ {//模擬節點流
public void readFile() {
System.out.println("對文件進行讀取...");
}
}
StringReader_:
package li.io;
public class StringReader_ extends Reader_ {//模擬節點流
public void readString() {
System.out.println("讀取字元串...");
}
}
BufferedReader_:
package li.io;
/**
* 模擬處理流(包裝流)
*/
public class BufferedReader_ extends Reader_ {
private Reader_ reader_;//屬性是Reader_類型
public BufferedReader_(Reader_ reader_) {
this.reader_ = reader_;
}
public void readFile(){//封裝一層
reader_.readFile();
}
//讓方法更加靈活,比如多次讀取文件,或者加緩衝byte[]...
public void readFile(int num) {
for (int i = 0; i < num; i++) {
reader_.readFile();
}
}
//又如擴展readString方法,例如批量處理字元串數據...
public void readString(int num) {
for (int i = 0; i < num; i++) {
reader_.readString();
}
}
}
Test_:
package li.io;
public class Test_ {
public static void main(String[] args) {
BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_());
bufferedReader_.readFile(3);
bufferedReader_.readFile();
BufferedReader_ bufferedReader02_ = new BufferedReader_(new StringReader_());
bufferedReader02_.readString(2);
}
}
4.4.3字元處理流-BufferedReader&BufferedWriter
-
BufferedReader和BufferedWriter屬於字元流,是按照字元來讀取數據的
-
在關閉流時,只需要關閉外層流(即包裝流)即可
- BufferedReader構造方法:
BufferedReader常用方法:
public int read() throws IOException
//讀取單個字元。
//作為一個整數(其範圍從 0 到 65535 (0x00-0xffff))讀入的字元,如果已到達流末尾,則返回 -1
public int read(char[] cbuf) throws IOException
//一次讀取一個位元組數組
//cbuf - 目標緩衝區
//讀取的字元數,如果已到達流的末尾,則返回 -1
public void close() throws IOException
//關閉該流並釋放與之關聯的所有資源。
public String readLine() throws IOException
//讀取一個文本行。通過下列字元之一即可認為某行已終止:換行 (’\n’)、回車 (’\r’) 或回車後直接跟著換行。
//包含該行內容的字元串,不包含任何行終止符,如果已到達流末尾,則返回 nu
- BufferedWriter構造方法:
BufferedWriter常用方法:
void write(char ch);//寫入單個字元。
void write(char []cbuf,int off,int len)//寫入字元數據的某一部分。
void write(String s,int off,int len)//寫入字元串的某一部分。
void newLine()//寫入一個行分隔符。
void flush();//刷新該流中的緩衝。將緩衝數據寫到目的文件中去。
void close();//關閉此流,在關閉前會先刷新
應用案例1:使用BufferedReader讀取文本文件,並顯示在控制台
package li.io.reader_;
import java.io.BufferedReader;
import java.io.FileReader;
//演示BufferedReader的使用
public class BufferedReader_ {
public static void main(String[] args) throws Exception {
String filePath = "d:\\note.txt";
//創建
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//讀取
String line;
//readLine():按行讀取文件,當返回null時,表示文件讀取完畢
while((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
//關閉流:這裡只需要關閉BufferedReader,底層會去自動地關閉節點流
bufferedReader.close();
}
}
思考:為什麼只需要關閉外層流?
在代碼bufferedReader.close();
處打上斷點,點擊force step into,可以看到下圖所示:
在底層調用的其實是:傳進去的節點流對象的close()方法
這裡的in就是我們傳入的new FileReader(filePath)
應用案例2:使用BufferedWriter將“一隻可愛的小貓咪”寫入到文件中
package li.io.writer_;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
//演示BufferedWriter的使用
public class BufferedWriter_ {
public static void main(String[] args) throws IOException {
String filePath = "d:\\ok.txt";
//創建BufferedWriter對象
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
//寫入
bufferedWriter.write("一隻可愛的小貓咪");
bufferedWriter.newLine();//插入一個和系統相關的換行
bufferedWriter.write("兩隻可愛的小貓咪");
bufferedWriter.newLine();
bufferedWriter.write("三隻可愛的小貓咪");
bufferedWriter.newLine();
//關閉外層流即可,底層自動關閉穿入的內層流
bufferedWriter.close();
}
}
案例3:綜合使用 BufferedReader & BufferedWriter 完成文件文本拷貝,註意文件編碼。
package li.io.writer_;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class BufferedCopy_ {
public static void main(String[] args) throws Exception {
//註意:BufferedReader 和 BufferedWriter都是字元流操作
// 不要去操作二進位文件[聲音,視頻,doc,pdf等],可能造成文件損壞
String srcFilePath = "d:\\note.txt";//源文件
String destFilePath = "d:\\note2.txt";
String line = null;
//創建BufferedReader&BufferedWriter對象
BufferedReader bufferedReader = new BufferedReader(new FileReader(srcFilePath));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
//讀入和寫出
while ((line = bufferedReader.readLine()) != null) {//每讀取一行內容就寫入
bufferedWriter.write(line);
bufferedWriter.newLine();//換行
}
System.out.println("拷貝完畢~");
//關閉兩個外層流
bufferedReader.close();
bufferedWriter.close();
}
}
4.4.4位元組處理流-BufferedInputStream&BufferedOutputStream
-
BufferedInputStream
BufferedInputStream是位元組流,在創建BufferedInputStream時會創建一個內部緩衝區數組。
常用方法:
int available()
//用於返回輸入流中可用的未讀位元組數,而不會由於下一次為此InputStream的方法的調用而阻塞。
void close()
//關閉此輸入流並釋放與該流關聯的所有系統資源。
void mark(int readlimit)
//輸入流的當前位置做個標記,readlimit參數是輸入流在標記位置失效前允許讀取的位元組數。
boolean markSupported()
//測試輸入流是否支持mark和reset方法。
int read()
//讀取一個位元組。
int read(byte[] b, int off, int len)
//讀取多個位元組到位元組數組b中,參數off是數組偏移量,參數len是讀取數據的長度。
void reset()
//重置流的當前位置到前面標記的位置。
long skip(long n)
//略過流中的數據。若數據不夠時,跳過僅有的位元組,返回跳過的位元組數。
-
BufferedOutputStream
BufferedOutputStream是位元組流,實現緩衝的輸出流,可以將多個位元組寫入底層的輸出流中,而不必對每次位元組寫入調用底層系統
應用案例:
要求:編程完成圖片/音樂的拷貝(要求使用 BufferedInputStream 和 BufferedOutputStream 流)
package li.io.outputstream_;
import java.io.*;
/**
* 演示使用 BufferedInputStream 和 BufferedOutputStream
* 使用它們可以拷貝二進位文件
* 同時也可以拷貝文本文件
*/
public class BufferedCopy02 {
public static void main(String[] args) {
String srcFilePath = "d:\\蘭亭序 - 周傑倫.mp3";
String destFilePath = "d:\\ltx-zhou.mp3";
//創建BufferedInputStream 和 BufferedOutputStream對象
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(srcFilePath));
bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
//迴圈寫入並讀取
byte[] buf = new byte[1024];
int readLen = 0;
//read(byte[]):當返回-1時就表示文件讀取完畢
while ((readLen = bis.read(buf)) != -1) {
bos.write(buf, 0, readLen);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//關閉外層流
try {
if (bos != null) {
bos.close();
}
if (bis != null) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
註意:位元組流可以操作二進位文件,同時也可以操作文本文件