解決BufferedReader.readLine()遇見的坑
BufferedReader.readLine()遇見的坑
在寫ftp上傳文件至服務(wù)器的過程中,有這樣一個(gè)判斷:判斷某個(gè)文件夾下有多少個(gè)文件,內(nèi)容為null的文件不上傳,所以利用BufferedReader讀取文件的內(nèi)容,判斷是否為null,所以用到了BufferedReader.readLine(),結(jié)果竟然卡死:txt、word、Excle、Ftp文件等都沒有問題,但是讀取MP3、Rar、zip等文件時(shí),就一直處于卡死狀態(tài),先看代碼:
package com.test; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; public class TestCh { public void readDocFileToFtp() { String docPath = "H:\\11"; // 文件所在路徑 模擬 File file; try { file = new File(docPath); File[] files = file.listFiles(); if (files.length == 0) { System.err.println(docPath + "文件夾下沒有任何文件!"); } else { Arrays.sort(files); System.err.println("文件數(shù)---" + files.length); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { InputStreamReader reader; reader = new InputStreamReader(new FileInputStream(files[i])); BufferedReader br = new BufferedReader(reader); String message = ""; String line = ""; long startTime = System.currentTimeMillis(); // 獲取開始時(shí)間 while ((line = br.readLine()) != null) { message += line; } br.close(); long endTime = System.currentTimeMillis(); // 獲取結(jié)束時(shí)間 System.out.println("程序運(yùn)行時(shí)間: " + (endTime - startTime) / 1000 + "ms"); String fileName = files[i].getName(); if (message.trim() == null || message.length() == 0) { System.err.println(fileName + "文件內(nèi)容為空!"); } else { // 上傳文件 System.err.println("上傳==============="); } } } } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { TestCh te = new TestCh(); te.readDocFileToFtp(); } }
然后一直卡死:
我們都知道,readLine()方法是遇到換行符或者是對(duì)應(yīng)流的結(jié)束符,該方法才會(huì)認(rèn)為讀到了一行(才會(huì)結(jié)束其阻塞),讓程序繼續(xù)往下執(zhí)行。但可能因?yàn)橐郧安涣粢?,也沒遇見過這種情況,所以就認(rèn)為該方法可放心使用
今天踩了這個(gè)坑,所以做個(gè)筆記
我們可能下意識(shí)地認(rèn)為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。
readLine()只有在數(shù)據(jù)流發(fā)生異常或者另一端被close()掉時(shí),才會(huì)返回null值。
如果不指定buffer大小,則readLine()使用的buffer有8192個(gè)字符。
在達(dá)到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才會(huì)返回。
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ù)處理
所以使用readLine()一定要注意
1.讀入的數(shù)據(jù)要注意有/r或/n或/r/n
2.沒有數(shù)據(jù)時(shí)會(huì)阻塞,在數(shù)據(jù)流異常或斷開時(shí)才會(huì)返回null
3.非必要時(shí)(socket之類的數(shù)據(jù)流),要避免使用readLine(),以免為了等待一個(gè)換行/回車符而一直阻塞
BufferedReader.readLine解析
bufferedreader.readline()加載流程:
br = new BufferedReader(reader,510241024);//設(shè)置緩存大小:5M
根據(jù)指定緩存大小,或默認(rèn)緩存大小,讀取文件內(nèi)容放到緩存中,在將緩存數(shù)據(jù)放在內(nèi)存中進(jìn)行讀取,等前一批內(nèi)存中的數(shù)據(jù)讀取完成后,
下一批緩存數(shù)據(jù)會(huì)放在內(nèi)存中進(jìn)行讀取;
按行讀取時(shí)等待讀取到換行符返回內(nèi)容;
注意:以上內(nèi)容都是自己理解的,僅為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 使用BufferedReader讀取TXT文件中數(shù)值,并輸出最大值
- 聊聊為什么要使用BufferedReader讀取File
- 關(guān)于BufferedReader的讀取效率問題
- 基于bufferedreader的read()與readline()讀取出錯(cuò)原因及解決
- Java?IO及BufferedReader.readline()出現(xiàn)的Bug
- 關(guān)于BufferedReader的read()和readLine()的區(qū)別
- Java基礎(chǔ)知識(shí)之BufferedReader流的使用
- 關(guān)于BufferedReader讀取文件指定字符集問題
相關(guān)文章
Java中l(wèi)ist集合為空或?yàn)閚ull的區(qū)別說明
這篇文章主要介紹了Java中l(wèi)ist集合為空或?yàn)閚ull的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Java guava monitor監(jiān)視器線程的使用詳解
工作中的場(chǎng)景中是否存在類似這樣的場(chǎng)景,需要提交的線程在某個(gè)觸發(fā)條件下執(zhí)行。本文主要就是使用guava中的monitor來優(yōu)雅的實(shí)現(xiàn)帶監(jiān)視器的線程2021-11-11java為移動(dòng)端寫接口開發(fā)實(shí)例
本篇文章主要介紹了java如何為移動(dòng)端寫接口,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08java幾種排序算法的實(shí)現(xiàn)及簡(jiǎn)單分析
這篇文章主要介紹了java幾種排序算法的實(shí)現(xiàn)及簡(jiǎn)單分析,實(shí)例分析了插入排序、希爾排序、選擇排序等常用排序算法,并分析了各個(gè)算法的優(yōu)劣,需要的朋友可以參考下2015-05-05Java中的lambda和stream實(shí)現(xiàn)排序
這篇文章主要介紹了Java中的lambda和stream實(shí)現(xiàn)排序,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09Java Stream 流實(shí)現(xiàn)合并操作示例
這篇文章主要介紹了Java Stream 流實(shí)現(xiàn)合并操作,結(jié)合實(shí)例形式詳細(xì)分析了Java Stream 流實(shí)現(xiàn)合并操作原理與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-05-05Java 中String StringBuilder 與 StringBuffer詳解及用法實(shí)例
這篇文章主要介紹了Java 中String StringBuilder 與 StringBuffer詳解及用法實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02