JavaIO?BufferedReader和BufferedWriter使用及說明
BufferedReader和BufferedWriter簡介
為了提高字符流讀寫的效率,引入了緩沖機制,進行字符批量的讀寫,提高了單個字符讀寫的效率。
BufferedReader用于加快讀取字符的速度,BufferedWriter用于加快寫入的速度
BufferedReader和BufferedWriter類各擁有8192個字符的緩沖區(qū)。當(dāng)BufferedReader在讀取文本文件時,會先盡量從文件中讀入字符數(shù)據(jù)并放滿緩沖區(qū),而之后若使用read()方法,會先從緩沖區(qū)中進行讀取。
如果緩沖區(qū)數(shù)據(jù)不足,才會再從文件中讀取,使用BufferedWriter時,寫入的數(shù)據(jù)并不會先輸出到目的地,而是先存儲至緩沖區(qū)中。如果緩沖區(qū)中的數(shù)據(jù)滿了,才會一次對目的地進行寫出。
BufferedReader
BufferedReader是為了提供讀的效率而設(shè)計的一個包裝類,它可以包裝字符流??梢詮淖址斎肓髦凶x取文本,緩沖各個字符,從而實現(xiàn)字符、數(shù)組和行的高效讀取。
構(gòu)造方法
方法 | 描述 |
---|---|
BufferedReader(Reader in) | 創(chuàng)建一個使用默認(rèn)大小輸入緩沖區(qū)的緩沖字符輸入流。 |
BufferedReader(Reader in, int sz) | 創(chuàng)建一個使用指定大小輸入緩沖區(qū)的緩沖字符輸入流。 |
成員方法
方法 | 描述 |
---|---|
int read() | 讀取單個字符。 |
int read(char[] cbuf, int off, int len) | 將字符讀入數(shù)組的某一部分。 |
String readLine() | 讀取一個文本行。 |
long skip(long n) | 跳過字符。 |
boolean ready() | 判斷此流是否已準(zhǔn)備好被讀取。 |
void close() | 關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源。 |
void mark(int readAheadLimit) | 標(biāo)記流中的當(dāng)前位置。 |
boolean markSupported() | 判斷此流是否支持 mark() 操作(它一定支持)。 |
void reset() | 將流重置到最新的標(biāo)記。 |
讀取文件實例
讀取文件: 一個字符一個字符的讀取
int read()方法,每次可以讀取到一個字符(以int 類型表示),不過因為返回的是int類型的,所以要強制類型轉(zhuǎn)換成char類型才能打印該字符。
public static void printByFileReader(String filePath) throws IOException { ? ? BufferedReader reader=new BufferedReader( ? ? ? ? ? ? new FileReader(filePath) ? ? ? ? ? ? ); ? ? if(!reader.ready()) ? ? { ? ? ? ? System.out.println("文件流暫時無法讀取"); ? ? ? ? return; ? ? } ? ? int result=0; ? ? while((result=reader.read())!=-1) ? ? { ? ? ? ? //因為讀取到的是int類型的,所以要強制類型轉(zhuǎn)換 ? ? ? ? System.out.print((char)result); ? ? } ? ? reader.close(); }
讀取文件:一個數(shù)組一個數(shù)組的讀取
int read(char[] cbuf, int off, int len)方法,每次讀取len個字符放到字符數(shù)組cbuf中,從數(shù)組cbuf的下表off開始放,返回的是每次讀取的字符個數(shù)。
public static void printByFileReaderChars(String filePath) throws IOException { ? ? BufferedReader reader=new BufferedReader( ? ? ? ? ? ? new FileReader(filePath) ? ? ? ? ? ? ); ? ? if(!reader.ready()) ? ? { ? ? ? ? System.out.println("文件流暫時無法讀取"); ? ? ? ? return; ? ? } ? ? int size=0; ? ? char[] cbuf=new char[20]; ? ? while((size=reader.read(cbuf, 0, cbuf.length))!=-1) ? ? { ? ? ? ? System.out.print(new String(cbuf,0,size)); ? ? } ? ? reader.close(); }
讀取文件:一行一行的讀取
String readLine()這個方法一次可以讀取一個文本行,返回的直接就是這一行的字符串,如果讀到行尾了就返回null。
public static void printByFileReaderLine(String filePath) throws IOException { ? ? BufferedReader reader=new BufferedReader( ? ? ? ? ? ? new FileReader(filePath) ? ? ? ? ? ? ); ? ? if(!reader.ready()) ? ? { ? ? ? ? System.out.println("文件流暫時無法讀取"); ? ? ? ? return; ? ? } ? ? int size=0; ? ? String line; ? ? while((line=reader.readLine())!=null) ? ? { ? ? ? ? System.out.print(line+"\n"); ? ? } ? ? reader.close(); }
需要注意的是:reader.readLine()方法返回的一行字符中不包含換行符,所以輸出的時候要自己加上換行符。
BufferedReader比FileReader高級的地方在于這個,F(xiàn)ileReader能一次讀取一個字符,或者一個字符數(shù)組。而BufferedReader也可以,同時BufferedReader還能一次讀取一行字符串。同時,BufferedReader帶緩沖,會比FileReader快很多。
但是FileReader使用項目的編碼來讀取解析字符,不能指定編碼,可能會出現(xiàn)編碼問題,如果要指定編碼可以使用包裝InputStreamReader的BufferedReader。這樣兼顧效率和編碼。
測試上述方法:
public static void main(String[] args) throws IOException { ? ? String fileutf8="utf8.txt"; ? ? String filegbk="gbk.txt"; ? ? //一個字符一個字符的讀取 ? ? printByFileReader(filegbk); ? ? System.out.println("\n---------------------------------------"); ? ? //一個字符數(shù)組一個字符數(shù)組的讀取 ? ? printByFileReaderChars(filegbk); ? ? System.out.println("\n---------------------------------------"); ? ? //一行一行的讀取 ? ? printByFileReaderLine(filegbk); ? ? System.out.println("#########################################"); ? ? //一個字符一個字符的讀取 ? ? printByFileReader(fileutf8); ? ? System.out.println("\n---------------------------------------"); ? ? //一個數(shù)組一個數(shù)組的讀取 ? ? printByFileReaderChars(fileutf8); ? ? System.out.println("\n---------------------------------------"); ? ? //一行一行的讀取 ? ? printByFileReaderLine(fileutf8); }
運行結(jié)果:
gbk file
這里是一句中文
---------------------------------------
gbk file
這里是一句中文
---------------------------------------
gbk file
這里是一句中文
#########################################
utf-8 file
榪欓噷鏄竴鍙ヤ腑鏂?
---------------------------------------
utf-8 file
榪欓噷鏄竴鍙ヤ腑鏂?
---------------------------------------
utf-8 file
榪欓噷鏄竴鍙ヤ腑鏂?
可以看到包裝FileReader的BufferedReader在讀取文件時候如果文件的編碼和項目的編碼不一樣的時候,會出現(xiàn)亂。
亂碼問題
使用包裝InputStreamReader的BufferedReader讀取文件
String file = "utf8.txt"; BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(file), "utf-8")); char[] cbuf=new char[20]; int size; while((size=reader.read(cbuf, 0, cbuf.length))!=-1) { System.out.println(new String(cbuf,0,size)); }
運行結(jié)果:
utf-8 file
這里是一句中文
這里要弄清楚的是BufferedReader只負(fù)責(zé)讀到它的內(nèi)部緩沖區(qū)中,而解碼的工作是InputStreamReader完成的。
BufferedWriter
BufferedWriter的API:
構(gòu)造函數(shù)
方法 | 描述 |
---|---|
BufferedWriter(Writer out) | 創(chuàng)建一個緩沖字符輸出流,使用默認(rèn)大小的輸出緩沖區(qū) |
BufferedWriter(Writer out, int sz) | 創(chuàng)建一個緩沖字符輸出流,使用給定大小的輸出緩沖區(qū) |
成員方法
方法 | 描述 |
---|---|
void write(int c) | 寫入單個字符。 |
void write(char[] cbuf, int off, int len) | 寫入字符數(shù)組的某一部分。 |
void write(String s, int off, int len) | 寫入字符串的某一部分。 |
void newLine() | 寫入一個行分隔符。 |
void close() | 關(guān)閉此流,但要先刷新它。 |
void flush() | 刷新該流的緩沖。 |
寫文件實例
使用上述三個寫方法寫文件:一個字符一個字符的復(fù)制文件
public static void main(String[] args) throws IOException { BufferedWriter writer=new BufferedWriter(new FileWriter("靜夜思.txt")); char ch='床'; //寫入一個字符 writer.write(ch); String next="前明月光,"; char[] nexts=next.toCharArray(); //寫入一個字符數(shù)組 writer.write(nexts,0,nexts.length); //寫入換行符 writer.newLine();//寫入換行符 String nextLine="疑是地上霜。"; //寫入一個字符串。 writer.write(nextLine); //關(guān)閉流 writer.close(); }
運行結(jié)果,靜夜思.txt:
床前明月光,
疑是地上霜。
應(yīng)用:復(fù)制文本文件
逐個字符復(fù)制文件
static void copyByChar(String srcFile, String destFile) throws IOException { ? ? BufferedReader reader = new BufferedReader(new FileReader(srcFile)); ? ? BufferedWriter writer = new BufferedWriter(new FileWriter(destFile)); ? ? int ch=0; ? ? //讀取一個字符 ? ? while ((ch = reader.read()) != -1) ? ? { ? ? ? ? //寫入一個字符 ? ? ? ? writer.write(ch); ? ? } ? ? reader.close(); ? ? writer.close(); }
逐個字符數(shù)組復(fù)制文件
static void copyByCharArray(String srcFile, String destFile) throws IOException { ? ? BufferedReader reader = new BufferedReader(new FileReader(srcFile)); ? ? BufferedWriter writer = new BufferedWriter(new FileWriter(destFile)); ? ? int size=0; ? ? char[] cbuf=new char[20]; ? ? //讀取一個字符數(shù)組 ? ? while ((size = reader.read(cbuf)) != -1) ? ? { ? ? ? ? //讀入多少寫入多少 ? ? ? ? writer.write(cbuf,0,size); ? ? } ? ? reader.close(); ? ? writer.close(); }
按行復(fù)制文件
static void copyByLine(String srcFile,String destFile) throws IOException { ? ? BufferedReader reader=new BufferedReader(new FileReader(srcFile)); ? ? BufferedWriter writer=new BufferedWriter(new FileWriter(destFile)); ? ? String line; ? ? //BufferedReader讀取一行的時候返回的字符串中不包括換行符 ? ? //如果有一行字符就返回該行字符串,沒有就返回null ? ? while((line=reader.readLine())!=null) ? ? { ? ? ? ? writer.write(line); ? ? ? ? writer.newLine();//寫換行符 ? ? } ? ? reader.close(); ? ? writer.close(); }
需要注意的是,BufferedReader的readLine()讀取一行的時候返回的字符串沒有換行符,所以,復(fù)制的時候?qū)懳募俏覀兒枚鄬懭胍粋€換行符,使用writer.newLine()方法即可。
測試
public static void main(String[] args) throws IOException { ? ? String from = "gbk.txt"; ? ? String to = "gbk_copy.txt"; ? ? String to1 = "gbk_copy1.txt"; ? ? String to2 = "gbk_copy2.txt"; ? ? copyByChar(from, to); ? ? copyByCharArray(from, to1); ? ? copyByLine(from, to2); }
源文件gbk.txt:
運行結(jié)果:
gbk_copy.txt
gbk file
這里是一句中文
gbk_copy1.txt
gbk file
這里是一句中文
gbk_copy2.txt
gbk file
這里是一句中文
bug:按行復(fù)制的時候多寫換行符
細(xì)心的朋友可能發(fā)現(xiàn),按行復(fù)制的時候,復(fù)制的文件會莫名其妙的在文件后面多了一個換行符。這是因為我們每次都在讀到的字符串后面寫一個換行符。
解決辦法:在讀到的字符串前面寫換行符,這樣出現(xiàn)新的問題,就是在文件開頭多出了一個空行,所以加入控制語句,在第一行不寫入換行符,第二行后再寫。
static void copyByLine(String srcFile,String destFile) throws IOException { ? ? BufferedReader reader=new BufferedReader(new FileReader(srcFile)); ? ? BufferedWriter writer=new BufferedWriter(new FileWriter(destFile)); ? ? String line; ? ? //BufferedReader讀取一行的時候返回的字符串中不包括換行符 ? ? //如果有一行字符就返回該行字符串,沒有就返回null ? ? boolean flag=false; ? ? while((line=reader.readLine())!=null) ? ? { ? ? ? ? if(!flag) ? ? ? ? { ? ? ? ? ? ? flag=true; ? ? ? ? ? ? writer.write(line); ? ? ? ? } ? ? ? ? else ? ? ? ? { ? ? ? ? ? ? writer.newLine();//寫換行符 ? ? ? ? ? ? writer.write(line); ? ? ? ? } ? ? } ? ? reader.close(); ? ? writer.close(); }
這樣復(fù)制的文件就不會多謝換行符了,保證復(fù)制的文件和源文件是一模一樣的。
bug:亂碼問題
因為我們使用的是包裝FileReader的BufferedReader,包裝FileWriter的BufferedWriter。所以讀字符,寫字符的時候使用的是默認(rèn)的字符編碼讀寫的。
所以讀寫文件的時候會出現(xiàn)亂碼,可以使用包裝InputStreamReader的BufferedReader,包裝OutputStreamWriter的BufferedWriter來復(fù)制文件,這樣就可以支持各種字符編碼。
實例:gbk編碼的文件復(fù)制到utf8編碼的文件中:
static void copyByLineEncoding(String srcFile, String srcEncoding, String destFile, ? ? ? ? String destEncoding) { ? ? BufferedReader reader = null; ? ? BufferedWriter writer = null; ? ? try ? ? { ? ? ? ? reader = new BufferedReader(new InputStreamReader( ? ? ? ? ? ? ? ? new FileInputStream(srcFile), srcEncoding)); ? ? ? ? writer = new BufferedWriter(new OutputStreamWriter( ? ? ? ? ? ? ? ? new FileOutputStream(destFile), destEncoding)); ? ? ? ? char[] charArray = new char[512]; ? ? ? ? int size; ? ? ? ? while ((size = reader.read(charArray, 0, charArray.length)) != -1) ? ? ? ? { ? ? ? ? ? ? writer.write(charArray, 0, size); ? ? ? ? } ? ? } catch (UnsupportedEncodingException | FileNotFoundException e) ? ? { ? ? ? ? e.printStackTrace(); ? ? } catch (IOException e) ? ? { ? ? ? ? e.printStackTrace(); ? ? } finally ? ? { ? ? ? ? if (writer != null) ? ? ? ? { ? ? ? ? ? ? try ? ? ? ? ? ? { ? ? ? ? ? ? ? ? writer.close(); ? ? ? ? ? ? } catch (IOException e) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? if (reader != null) ? ? ? ? { ? ? ? ? ? ? try ? ? ? ? ? ? { ? ? ? ? ? ? ? ? reader.close(); ? ? ? ? ? ? } catch (IOException e) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
main方法:
public static void main(String[] args) throws IOException { ? ? String from = "gbk.txt"; ? ? String to = "copyto_utf8.txt"; ? ? copyByLineEncoding(from,"gbk",to,"utf-8"); }
源文件gbk.txt(gbk編碼):
gbk file
這里是一句中文
目標(biāo)文件copyto_utf8.txt:
utf-8 file
榪欓噷鏄竴鍙ヤ腑鏂?
亂碼是正常的,因為我們的工程目錄用的gbk編碼,把copyto_utf8.txt編碼顯示就好了:
utf-8 file
這里是一句中文
所以使用包裝InputStreamReader的BufferedReader,包裝OutputStreamWriter的BufferedWriter來復(fù)制文件的好處就是可以指定復(fù)制文件的時候使用的字符編碼,例如上面的復(fù)制操作,從gbk編碼的文件中讀取,然后寫入到utf8編碼的文件中去。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決java.net.SocketTimeoutException: Read timed out的問題
這篇文章主要介紹了解決java.net.SocketTimeoutException: Read timed out的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06SpringBoot框架RESTful接口設(shè)置跨域允許
這篇文章主要為大家詳細(xì)介紹了SpringBoot框架RESTful接口設(shè)置跨域允許,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-08-08SpringBoot實現(xiàn)設(shè)置全局和局部時間格式化
本文主要介紹了SpringBoot實現(xiàn)設(shè)置全局和局部時間格式化,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01