關于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()來了。

?

發數據:

?

[java]?view plaincopy
  1. BufferedWriter?output?=?new?BufferedWriter(new?OutputStreamWriter(conn.openOutputStream()));???
  2. int?i?=?1;??
  3. String?message?=?"message?"?+?i;??
  4. while(isRunning)?{??
  5. ????output.write(message+"/n");???
  6. ????i++;??
  7. }??

?

?

?

讀數據:

?

[java]?view plaincopy
  1. BufferedReader?input?=?new?BufferedReader(new??InputStreamReader(m_conn.openInputStream()));??
  2. String?message?=?"";??
  3. String?line?=?null;??
  4. while((line?=?m_input.readLine())?!=?null)?{??
  5. ????message?+=?line;??
  6. }??
  7. 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()的實質(下面是從JDK源碼摘出來的):

?

[java]?view plaincopy
  1. String?readLine(boolean?ignoreLF)?throws?IOException?{??
  2. ????StringBuffer?s?=?null;??
  3. ????int?startChar;??
  4. ????????synchronized?(lock)?{??
  5. ????????????ensureOpen();??
  6. ????????boolean?omitLF?=?ignoreLF?||?skipLF;??
  7. ????????bufferLoop:??
  8. ????????for?(;;)?{??
  9. ????????if?(nextChar?>=?nChars)??
  10. ????????????fill();?//在此讀數據??
  11. ????????if?(nextChar?>=?nChars)?{?/*?EOF?*/??
  12. ????????????if?(s?!=?null?&&?s.length()?>?0)??
  13. ????????????return?s.toString();??
  14. ????????????else??
  15. ????????????return?null;??
  16. ????????}??
  17. ??????......//其它??
  18. }??
  19. ??
  20. private?void?fill()?throws?IOException?{??
  21. ????..../其它??
  22. ????int?n;??
  23. ????do?{??
  24. ????????n?=?in.read(cb,?dst,?cb.length?-?dst);?//實質??
  25. ????}?while?(n?==?0);??
  26. ????if?(n?>?0)?{??
  27. ????????nChars?=?dst?+?n;??
  28. ????????nextChar?=?dst;??
  29. ????}??
  30. ????}??

?

從上面看出,readLine()是調用了read(char[] cbuf, int off, int len) 來讀取數據,后面再根據"/r"或"/n"來進行數據處理。

?

在Java?I/O書上也說了:

public String readLine() throws IOException
This method returns a string that contains a line of text from a text file. /r, /n, and /r/n are assumed to be line breaks and are not included in the returned string. This method is often used when reading user input from System.in, since most platforms only send the user's input to the running program after the user has typed a full line (that is, hit the Return key).
readLine() has the same problem with line ends that DataInputStream's readLine() method has; that is,?the potential to hang on a lone carriage return that ends the stream?. This problem is especially acute on networked connections, where readLine() should never be used.

?

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

  1. 讀入的數據要注意有/r或/n或/r/n
  2. 沒有數據時會阻塞,在數據流異常或斷開時才會返回null
  3. 使用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);
???}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/253315.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/253315.shtml
英文地址,請注明出處:http://en.pswp.cn/news/253315.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HDCVI——一種創新性的高清視頻傳輸方案

什么是HDCVI 2012年11月,大華技術股份有限公司發布了具有自主知識產權的同軸高清傳輸接口技術HDCVI。HDCVI技術是一種基于已有SYV75-3或SYV75-5同軸電纜的高清視頻傳輸方法,能夠在低成本和較低質量的同軸電纜上實現超長距離高清視頻信號的可靠傳輸。相比…

typedef struct 用法

如果在c程序中我們寫:    typedef struct     {    int num;    int age;    }aaa,bbb,ccc;    這算什么呢?    我個人觀察編譯器(VC6)的理解,這相當于    typedef struct     …

智能機器人品牌簡介

隨著科技的發展,硬件的計算速度和大數據支撐,越來越多的智能化設備和產品出現在我們的面前,為我們的生活帶來更多便利。其中包括智能機器人,這種產品是有自己的“大腦”,可以接收人為指令,為人服務&#xf…

轉 Java對日期Date類進行加減運算一二三

請移步,https://blog.csdn.net/hacker_lees/article/details/74351838 ,感謝博主分享轉載于:https://www.cnblogs.com/bestxyl/p/9790088.html

誕生之日 隨筆

今天我誕生了,祝自己誕生日happy,happy,happy! 轉載于:https://www.cnblogs.com/xiaohuihui-/p/7594406.html

智能音箱 之 麥克風參數介紹

1. 定義 麥克風,學名為傳聲器,是將聲音信號轉換為電信號的能量轉換器件;聲—電轉換。 與揚聲器正好相反(電—聲轉換),構成電聲設備的兩個終端,俗稱咪頭,麥克等。 是電聲系統的入口&a…

大屏幕行業發展現狀以及趨勢深刻剖析

瀏覽數: 689 海康威視:葉志龍 中國投影網:大屏幕顯示作為安防領域重要一環,而海康威視作為安防領域的佼佼者,請介紹海康威視大屏顯示系統DLP/LCD這兩大產品線?與行業同類產品相比,海康威視大屏拼接單元產品…

架構師是大忽悠嗎?阿里技術大牛告訴你真相!

來源:阿里云 作者:林昊(花名畢玄),阿里巴巴技術保障部研究員,曾任淘寶網平臺架構部架構師。個人的研究方向主要為Java模塊化、動態化系統的構建,以及高性能大型分布式Java系統構建,主…

動手動腦-Java重載

有以下例子: 例: Using overloaded methods public class MethodOverload { public static void main(String[] args) { System.out.println("The square of integer 7 is " square(7)); System.out.println("\nThe square of double 7.…

利用django框架,手把手教你搭建數據可視化系統(一)

如何使用django去構建數據可視化的 web,可視化的結果可以呈現在web上。 使用django的MTV模型搭建網站 基礎鋪墊—MTV模型 Created with Raphal 2.1.0Request服務器(Djangoweb)Response首先,要搞清楚我們去訪問服務器,服務器返回信…

智能音箱 之 揚聲器喇叭介紹

在全雙工語音交互的系統中,功放的質量是非常重要的,因為AEC回聲消除對信號失真 是非常敏感的。音頻通路的整體諧波失真需要控制在5%以內。 對于整個系統的諧波失真來說,揚聲器是最關鍵的因素,其次是功放,麥克風的很小…

關于拓撲排序的問題-P3116 [USACO15JAN]會議時間Meeting Time

https://www.luogu.org/problem/show?pid3116 這道題目很水啊,但是我沒有1A,而且wa了好多; 題目意思我就不講了; 反正就是一個拓撲序dp; 但是這道題目規定了起點是1; 所以我一開始直接把1放進隊列里然…

HD-SDI DVR發展與應用剖析

自2010年以來,視頻監控已經進入“高清”監控時代;隨著高清的發展,HD-SDI高清數字系統開始進入人們的視線,在大、小展會上均可以輕松找到“數字高清”的產品和解決方案。作為HD-SDI系統中編碼、存儲部分的HD-SDI高清數字硬盤錄像機…

UML學習——類圖(三)

1.類圖 UML類圖是用來描述類、接口、協作及它們之間的關系的圖。用來顯示系統中各個類的靜態結構。 2.類圖的組成元素 類圖由以下六種元素組成:類,接口,泛化關系,關聯關系,依賴關系,實現關系。 3.類圖的繪制…

傳錘子科技解散成都分公司 才搬遷一年羅永浩就頂不住了

雷帝網 樂天 10月16日報道今日有網友爆料,錘子科技解散成都分公司。有網友指出,爆料的人是錘子科技早期員工王前闖。網友爆料錘子成都研發中心解散網友爆料錘子成都研發中心解散2016年,錘子科技虧損4億元,一直徘徊在破產的邊緣&am…

智能音箱 之 功放與揚聲器(喇叭)的匹配關系

1. 功放的概念   功率放大器簡稱功放,俗稱 “擴音機”,是音響系統中最基本的設備,它的任務是把來自信號源(專業音響系統中則是來自調音臺)的微弱電信號進行放大以驅動揚聲器發出聲音。 2. 功放的分類 功率放大器分…

前端性能優化 Web前端應該從哪些方面來優化網站?

作者:斯迪鏈接:https://www.zhihu.com/question/21658448/answer/18903129來源:知乎著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。前端是龐大的,包括 HTML、 CSS、 Javascript、Image 、Flash…

嵌入式NVR發展淺析

隨著視頻監控的高速發展,視頻監控對硬盤錄像機的要求也在不斷提高,在以往“看得見”的基礎上,要求視頻畫面看的更為清晰、準確。相對于傳統硬盤錄像機,NVR最主要的特征就是“網絡化”、“高清化”,在視頻監控“高清化”…

Maven and Nexus2

2019獨角獸企業重金招聘Python工程師標準>>> Maven and Nexus2 Maven是什么? 構建工具: 通過簡單的命令,能夠完成清理、編譯、測試、打包、部署等一系列過程。同時,不得不提的是,Maven是跨平臺的&#xff0…

Linux kernel的中斷子系統之(九):tasklet

返回目錄:《ARM-Linux中斷系統》。 總結: 二介紹了tasklet存在的意義。 三介紹了通過tasklet_struct來抽想一個tasklet,每個CPU維護一個tasklet鏈表tasklet_vec/tasklet_hi_vec,然后介紹了如何定一個一個tasklet(靜態/動態)&#…