java中br.readline_Java:java中BufferedReader的read()及readLine()方法的使用心得
BufferedReader的readLine()方法是阻塞式的, 如果到達(dá)流末尾, 就返回null, 但如果client的socket末經(jīng)關(guān)閉就銷毀, 則會(huì)產(chǎn)生IO異常. 正常的方法就是使用socket.close()關(guān)閉不需要的socket.
從一個(gè)有若干行的文件中依次讀取各行,處理后輸出,如果用以下方法,則會(huì)出現(xiàn)除第一行外行首字符丟失現(xiàn)象.
String str? = null;
br=new BufferedReader(new FileReader(fileName));
do{
str = buf.readLine());
}while(br.read()!=-1);
以下用法會(huì)使每行都少首字符
while(br.read() != -1){
str = br.readLine();
}
原因就在于br.read() != -1 這判斷條件上。 因?yàn)樵趫?zhí)行這個(gè)條件的時(shí)候其實(shí)它已經(jīng)讀取了一個(gè)字符了,然而在這里并沒有對(duì)讀取出來的這個(gè)字符做處理,所以會(huì)出現(xiàn)少一個(gè)字符,如果你這里寫的是while(br.readLine()!=null)會(huì)出現(xiàn)隔一行少一行!
建議使用以下方法
String str = null;
while((str = br.readLine()) != null){
//System.out.println(str);//此時(shí)str就保存了一行字符串
}
這樣應(yīng)該就可以無字符丟失地得到一行了
雖然寫IO方面的程序不多,但BufferedReader/BufferedInputStream倒是用過好幾次的,原因是:
它有一個(gè)很特別的方法:readLine(),使用起來特別方便,每次讀回來的都是一行,省了很多手動(dòng)拼接buffer的瑣碎;
它比較高效,相對(duì)于一個(gè)字符/字節(jié)地讀取、轉(zhuǎn)換、返回來說,它有一個(gè)緩沖區(qū),讀滿緩沖區(qū)才返回;一般情況下,都建議使用它們把其它Reader/InputStream包起來,使得讀取數(shù)據(jù)更高效。
對(duì)于文件來說,經(jīng)常遇到一行一行的,特別相符情景。
這次是在藍(lán)牙開發(fā)時(shí),使用兩個(gè)藍(lán)牙互相傳數(shù)據(jù)(即一個(gè)發(fā)一個(gè)收),bluecove這個(gè)開源組件已經(jīng)把數(shù)據(jù)讀取都封裝成InputStream了,也就相當(dāng)于平時(shí)的IO讀取了,很自然就使用起readLine()來了。
發(fā)數(shù)據(jù):
BufferedWriter?output?=?new?BufferedWriter(new?OutputStreamWriter(conn.openOutputStream()));
int?i?=?1;
String?message?=?"message?"?+?i;
while(isRunning)?{
output.write(message+"/n");
i++;
}
讀數(shù)據(jù):
BufferedReader?input?=?new?BufferedReader(new??InputStreamReader(m_conn.openInputStream()));
String?message?=?"";
String?line?=?null;
while((line?=?m_input.readLine())?!=?null)?{
message?+=?line;
}
System.out.println(message);
上面是代碼的節(jié)選,使用這段代碼會(huì)發(fā)現(xiàn)寫數(shù)據(jù)時(shí)每次都成功,而讀數(shù)據(jù)側(cè)卻一直沒有數(shù)據(jù)輸出(除非把流關(guān)掉)。經(jīng)過折騰,原來這里面有幾個(gè)大問題需要理解:
誤以為readLine()是讀取到?jīng)]有數(shù)據(jù)時(shí)就返回null(因?yàn)槠渌黵ead方法當(dāng)讀到?jīng)]有數(shù)據(jù)時(shí)返回-1),而實(shí)際上readLine()是一個(gè)阻塞函數(shù),當(dāng)沒有數(shù)據(jù)讀取時(shí),就一直會(huì)阻塞在那,而不是返回null;因?yàn)閞eadLine()阻塞后,System.out.println(message)這句根本就不會(huì)執(zhí)行到,所以在接收端就不會(huì)有東西輸出。要想執(zhí)行到System.out.println(message),一個(gè)辦法是發(fā)送完數(shù)據(jù)后就關(guān)掉流,這樣readLine()結(jié)束阻塞狀態(tài),而能夠得到正確的結(jié)果,但顯然不能傳一行就關(guān)一次數(shù)據(jù)流;另外一個(gè)辦法是把System.out.println(message)放到while循環(huán)體內(nèi)就可以。
readLine()只有在數(shù)據(jù)流發(fā)生異常或者另一端被close()掉時(shí),才會(huì)返回null值。
如果不指定buffer大小,則readLine()使用的buffer有8192個(gè)字符。在達(dá)到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才會(huì)返回。
readLine()的實(shí)質(zhì)(下面是從JDK源碼摘出來的):
String?readLine(boolean?ignoreLF)?throws?IOException?{
StringBuffer?s?=?null;
int?startChar;
synchronized?(lock)?{
ensureOpen();
boolean?omitLF?=?ignoreLF?||?skipLF;
bufferLoop:
for?(;;)?{
if?(nextChar?>=?nChars)
fill();?//在此讀數(shù)據(jù)
if?(nextChar?>=?nChars)?{?/*?EOF?*/
if?(s?!=?null?&&?s.length()?>?0)
return?s.toString();
else
return?null;
}
......//其它
}
private?void?fill()?throws?IOException?{
..../其它
int?n;
do?{
n?=?in.read(cb,?dst,?cb.length?-?dst);?//實(shí)質(zhì)
}?while?(n?==?0);
if?(n?>?0)?{
nChars?=?dst?+?n;
nextChar?=?dst;
}
}
從上面看出,readLine()是調(diào)用了read(char[] cbuf, int off, int len) 來讀取數(shù)據(jù),后面再根據(jù)"/r"或"/n"來進(jìn)行數(shù)據(jù)處理。
小結(jié),使用readLine()一定要注意:
讀入的數(shù)據(jù)要注意有/r或/n或/r/n
沒有數(shù)據(jù)時(shí)會(huì)阻塞,在數(shù)據(jù)流異常或斷開時(shí)才會(huì)返回null
使用socket之類的數(shù)據(jù)流時(shí),要避免使用readLine(),以免為了等待一個(gè)換行/回車符而一直阻塞
1.讀取一個(gè)txt文件,方法很多種我使用了字符流來讀取(為了方便)
FileReader fr = new FileReader("f:\\TestJava.Java");
BufferedReader bf = new BufferedReader(fr);
//這里進(jìn)行讀取
int b;
while((b=bf.read())!=-1){
System.out.println(bf.readLine());
}
發(fā)現(xiàn)每行的第一個(gè)字符都沒有顯示出來,原因呢:b=bf.read())!=-1? 每次都會(huì)先讀取一個(gè)字節(jié)出來,所以后面的bf.readLine())讀取的就會(huì)每行少一個(gè)字節(jié),所以,應(yīng)該使用
String valueString = null;
while ((valueString=bf.readLine())!=null){
System.out.println(valueString);
}
總結(jié)
以上是生活随笔為你收集整理的java中br.readline_Java:java中BufferedReader的read()及readLine()方法的使用心得的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 360安全卫士中360leakfixer
- 下一篇: HALO系统又立功了 中国车手周冠宇发照