基于bufferedreader的read()與readline()讀取出錯原因及解決
bufferedreader的read()與readline()讀取出錯
以前學(xué)習(xí)java的時候也沒有太在意,直到最近做項目時使用了才發(fā)現(xiàn)這個問題,總是第一個字符輸不出來
bufferedreader這個類借用別人的話來說,就是一個包裝類
它可以包裝字符流,將字符流放入緩存里,先把字符讀到緩存里,到緩存滿了或者你flush的時候,再讀入內(nèi)存,就是為了提高讀的效率而設(shè)計的。
讀取一個txt文件,方法很多種而我使用的是字符流來讀取
int c; FileReader file = new FileReader("D:\\emDemo.java"); BufferedReader br = new BufferedReader(file); while((c=br.read())!=-1){undefined System.out.println(br.readLine()); }
發(fā)現(xiàn)每行的第一個字符都沒有顯示出來,后來發(fā)現(xiàn) c=br.read())!=-1 每次都會先讀取一個字節(jié)出來,所以后面的br.readLine());
讀取的就是每行少一個字節(jié)
所以,應(yīng)該使用
String input = null; while ((input=br.readLine())!=null){undefined System.out.println(input); }
這樣就能解決了~
bufferedReader中的readLine()源碼解析
String readLine(boolean ignoreLF) throws IOException { //行(hang)數(shù)據(jù)的緩沖s StringBuffer s = null; int startChar; synchronized (lock) { /*確保被bufferedReader包裝的輸入流沒有關(guān)閉*/ ensureOpen(); /* 如果 讀到'\r',skipLF置為true, * 這是skip()方法里面的部分代碼,它展示了通過skipLF來忽略'\n' * if (skipLF) { skipLF = false; if (cb[nextChar] == '\n') { nextChar++; } } *ignoreLF一直就是false **/ boolean omitLF = ignoreLF || skipLF; /* bufferLoop主要是不斷地遍歷底層的數(shù)組cb,并取兩個換行符之間的數(shù)據(jù)付給行緩沖s。當(dāng)?shù)讓訑?shù)組遍歷完要用fill()把數(shù)據(jù)從流中填充到cb,直到流的末尾 *charloop,主要是遍歷緩沖數(shù)組cb,以確定'\n','\r'的位置 nextChar:下次讀取緩沖字符數(shù)組cb的位置, nChars:緩沖字符數(shù)組cb的length */ bufferLoop: for (;;) { //1、如果緩沖數(shù)組的數(shù)據(jù)不足,或者已經(jīng)讀到了數(shù)組的末尾時: //1.1如果下次讀取的位置已經(jīng)到了or超過數(shù)組的長度,從流中讀數(shù)據(jù)到緩沖數(shù)組cb中 if (nextChar >= nChars) fill(); /*1.2如果從流中讀數(shù)據(jù)到數(shù)組cb之后, nextChar,nChars的大小關(guān)系沒有改變. 說明到了文件的末尾,END OF FILE.返回s */ if (nextChar >= nChars) { /* EOF */ if (s != null && s.length() > 0) return s.toString(); else return null; } //2 緩沖數(shù)組中有足夠的數(shù)據(jù)時: /*從本個換行符所在的索引位置開始,遍歷char [] cb ,直到找到\n \r,把兩個換行符之間的字符序列填充進s *eol:END OF LINE *類屬性char [] cb ,也就是bufferReader類的緩沖數(shù)組。length由構(gòu)造器指定,若不指定默認為8 * 1024 = 8192,與內(nèi)存頁大小密切相關(guān) * */ boolean eol = false; char c = 0; int i; if (omitLF && (cb[nextChar] == '\n')) nextChar++; skipLF = false; omitLF = false; charLoop: for (i = nextChar; i < nChars; i++) { c = cb[i]; if ((c == '\n') || (c == '\r')) { eol = true; break charLoop; } } /*2.1找到換行符后,從上個換行符到本換行符之間的序列,填充給s*/ startChar = nextChar; nextChar = i; if (eol) { String str; /*2.1.1如果是第一次遍歷到換行符,*/ if (s == null) { str = new String(cb, startChar, i - startChar); } /*2.1.2至少遍歷到一次換行符時*/ else { s.append(cb, startChar, i - startChar); str = s.toString(); } //更新下次讀取的位置 nextChar++; if (c == '\r') { skipLF = true; } return str; } //2.2如果沒有換行符 if (s == null) //類屬性int defaultExpectedLineLength = 80 s = new StringBuffer(defaultExpectedLineLength); //填充s,從上個換行符到最后 s.append(cb, startChar, i - startChar); } } }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MyBatis?多表聯(lián)合查詢及優(yōu)化方法
大家都知道Hibernate 是全自動的數(shù)據(jù)庫持久層框架,它可以通過實體來映射數(shù)據(jù)庫,通過設(shè)置一對多、多對一、一對一、多對多的關(guān)聯(lián)來實現(xiàn)聯(lián)合查詢,接下來通過本文給大家介紹MyBatis?多表聯(lián)合查詢及優(yōu)化,需要的朋友可以參考下2022-08-08Oracle + Mybatis實現(xiàn)批量插入、更新和刪除示例代碼
利用MyBatis動態(tài)SQL的特性,我們可以做一些批量的操作,下面這篇文章主要給大家介紹了關(guān)于Oracle + Mybatis實現(xiàn)批量插入、更新和刪除的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。2018-01-01java?list和map切割分段的實現(xiàn)及多線程應(yīng)用案例
這篇文章主要為大家介紹了java?list和map切割分段的實現(xiàn)及多線程應(yīng)用案例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12關(guān)于使用swagger整合springMVC的方法
在平時開發(fā)寫接口文檔的工作時,一般都是word文檔,帶來書寫麻煩、維護麻煩的問題,比如改了源代碼忘了更新文檔、解釋不明確帶來歧義、無法在線嘗試等等,swagger可以有效解決這類問題,需要的朋友可以參考下2023-04-04