java中br.readline_Java:java中BufferedReader的read()及readLine()方法的使用心得
BufferedReader的readLine()方法是阻塞式的, 如果到達流末尾, 就返回null, 但如果client的socket末經關閉就銷毀, 則會產生IO異常. 正常的方法就是使用socket.close()關閉不需要的socket.
從一個有若干行的文件中依次讀取各行,處理后輸出,如果用以下方法,則會出現除第一行外行首字符丟失現象.
String str? = null;
br=new BufferedReader(new FileReader(fileName));
do{
str = buf.readLine());
}while(br.read()!=-1);
以下用法會使每行都少首字符
while(br.read() != -1){
str = br.readLine();
}
原因就在于br.read() != -1 這判斷條件上。 因為在執行這個條件的時候其實它已經讀取了一個字符了,然而在這里并沒有對讀取出來的這個字符做處理,所以會出現少一個字符,如果你這里寫的是while(br.readLine()!=null)會出現隔一行少一行!
建議使用以下方法
String str = null;
while((str = br.readLine()) != null){
//System.out.println(str);//此時str就保存了一行字符串
}
這樣應該就可以無字符丟失地得到一行了
雖然寫IO方面的程序不多,但BufferedReader/BufferedInputStream倒是用過好幾次的,原因是:
它有一個很特別的方法:readLine(),使用起來特別方便,每次讀回來的都是一行,省了很多手動拼接buffer的瑣碎;
它比較高效,相對于一個字符/字節地讀取、轉換、返回來說,它有一個緩沖區,讀滿緩沖區才返回;一般情況下,都建議使用它們把其它Reader/InputStream包起來,使得讀取數據更高效。
對于文件來說,經常遇到一行一行的,特別相符情景。
這次是在藍牙開發時,使用兩個藍牙互相傳數據(即一個發一個收),bluecove這個開源組件已經把數據讀取都封裝成InputStream了,也就相當于平時的IO讀取了,很自然就使用起readLine()來了。
發數據:
BufferedWriter?output?=?new?BufferedWriter(new?OutputStreamWriter(conn.openOutputStream()));
int?i?=?1;
String?message?=?"message?"?+?i;
while(isRunning)?{
output.write(message+"/n");
i++;
}
讀數據:
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);
上面是代碼的節選,使用這段代碼會發現寫數據時每次都成功,而讀數據側卻一直沒有數據輸出(除非把流關掉)。經過折騰,原來這里面有幾個大問題需要理解:
誤以為readLine()是讀取到沒有數據時就返回null(因為其它read方法當讀到沒有數據時返回-1),而實際上readLine()是一個阻塞函數,當沒有數據讀取時,就一直會阻塞在那,而不是返回null;因為readLine()阻塞后,System.out.println(message)這句根本就不會執行到,所以在接收端就不會有東西輸出。要想執行到System.out.println(message),一個辦法是發送完數據后就關掉流,這樣readLine()結束阻塞狀態,而能夠得到正確的結果,但顯然不能傳一行就關一次數據流;另外一個辦法是把System.out.println(message)放到while循環體內就可以。
readLine()只有在數據流發生異?;蛘吡硪欢吮籧lose()掉時,才會返回null值。
如果不指定buffer大小,則readLine()使用的buffer有8192個字符。在達到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才會返回。
readLine()的實質(下面是從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();?//在此讀數據
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);?//實質
}?while?(n?==?0);
if?(n?>?0)?{
nChars?=?dst?+?n;
nextChar?=?dst;
}
}
從上面看出,readLine()是調用了read(char[] cbuf, int off, int len) 來讀取數據,后面再根據"/r"或"/n"來進行數據處理。
小結,使用readLine()一定要注意:
讀入的數據要注意有/r或/n或/r/n
沒有數據時會阻塞,在數據流異?;驍嚅_時才會返回null
使用socket之類的數據流時,要避免使用readLine(),以免為了等待一個換行/回車符而一直阻塞
1.讀取一個txt文件,方法很多種我使用了字符流來讀取(為了方便)
FileReader fr = new FileReader("f:\\TestJava.Java");
BufferedReader bf = new BufferedReader(fr);
//這里進行讀取
int b;
while((b=bf.read())!=-1){
System.out.println(bf.readLine());
}
發現每行的第一個字符都沒有顯示出來,原因呢:b=bf.read())!=-1? 每次都會先讀取一個字節出來,所以后面的bf.readLine())讀取的就會每行少一個字節,所以,應該使用
String valueString = null;
while ((valueString=bf.readLine())!=null){
System.out.println(valueString);
}
總結
以上是生活随笔為你收集整理的java中br.readline_Java:java中BufferedReader的read()及readLine()方法的使用心得的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 360安全卫士中360leakfixer
- 下一篇: java数组元素是类_Java数组及其常