關於java中BufferedReader的read()及readLine()方法的使用心得


  BufferedReader的readLine()方法是阻塞式的, 如果到達流末尾, 就返回null, 但如果client的socket末經關閉就銷毀, 則會產生IO異常. 正常的方法就是使用socket.close()關閉不需要的socket.

  雖然寫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()只有在數據流發生異常或者另一端被close()掉時,才會返回null值。
  • 如果不指定buffer大小,則readLine()使用的buffer有8192個字符。在達到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才會返回。

小結,使用readLine()一定要注意

  1. 讀入的數據要注意有/r或/n或/r/n
  2. 沒有數據時會阻塞,在數據流異常或斷開時才會返回null
  3. 使用socket之類的數據流時,要避免使用readLine(),以免為了等待一個換行/回車符而一直阻塞

正確讀取Socket InputStream 的方法

package com.photoManage.utils;

import java.io.*;  

public class StreamTool {     
    public static void main(String[] args) {  
        try {  
            File file = new File("C:\\demo.log");  
            FileInputStream fin = new FileInputStream(file);  
            byte[] filebt = readStream(fin);  
            System.out.println(filebt.length);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }     
    }
    
    /** 
     * @功能 讀取流 
     * @param inStream 
     * @return 字節數組 
     * @throws Exception 
     */  
    public static byte[] readStream(InputStream inStream) throws Exception {  
        int count = 0;
        while (count == 0) {
            count = inStream.available();
        }
        byte[] b = new byte[count];
        inStream.read(b);
        return b; 
    }  
}  

參考博客:

http://cuisuqiang.iteye.com/blog/1434416#comments

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM