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

