Java?IO及BufferedReader.readline()出現(xiàn)的Bug
Java IO及BufferedReader.readline()的Bug
IO流
流:流是一組有序的,有起點(diǎn)和終點(diǎn)的字節(jié)集合,是對(duì)計(jì)算機(jī)中數(shù)據(jù)傳輸?shù)目偡Q。即數(shù)據(jù)在兩個(gè)設(shè)備間的傳輸稱為流,流的本質(zhì)是數(shù)據(jù)傳輸。
BufferedReader.readline()方法Bug
錯(cuò)誤代碼:
File testTxt = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test.txt"); File file_copy3 = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test_copy3.txt"); BufferedReader bufferedReader = new BufferedReader(new FileReader(testTxt)); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file_copy3)); //readLine() 每次讀取一行 while (bufferedReader.readLine() != null){ System.out.println(bufferedReader.readLine()); bufferedWriter.write(bufferedReader.readLine()); } bufferedWriter.close(); bufferedReader.close();
原文件:
結(jié)果:
結(jié)果控制臺(tái)只打印了第二行,最后還報(bào)錯(cuò)了空指針異常
原因:
是代碼中每次調(diào)用readline()方法,就會(huì)向下讀取一行所以錯(cuò)誤代碼中表示的是while 判斷 的第一行不為null,打印的是第二行 ,然后寫(xiě)入的是第三行,在次while判斷的是第四行 有內(nèi)容,打印的是第五行 為null,寫(xiě)入的是第六行也為null,就導(dǎo)致了空指針異常。
修改后的代碼:
String line; while ((line = bufferedReader.readLine()) != null){ System.out.println(line); bufferedWriter.write(line); }
結(jié)果:
注意:只用readline()復(fù)制后的但是和原文件是不同,沒(méi)有了換行符,如果需要可以在while循環(huán)體內(nèi)加上/r/n
源碼
package com.lsh.io; import java.io.*; import java.time.Duration; import java.time.Instant; /** * @author :LiuShihao * @date :Created in 2021/3/3 11:09 上午 * @desc : 只要是處理純文本數(shù)據(jù),就優(yōu)先考慮使用字符流。除此之外都使用字節(jié)流。 * */ public class FileIO { public static File testTxt = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test.txt"); public static File catImg = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/cat.jpg"); public static void main(String[] args) throws Exception { Instant now = Instant.now(); System.out.println("開(kāi)始復(fù)制:"+now); // copyFile(); // copyByReaderAndWriter1(); copyByReaderAndWriter2(); Instant end = Instant.now(); // Duration 期間Instant Period 時(shí)期 LocalDateTime System.out.println("復(fù)制完成:"+end+",耗時(shí):"+ Duration.between(now,end)); } /** * 使用FileinputStream、FileOutputStream 與原文件一樣 * 將一個(gè)文件復(fù)制一份 */ public static void copyFile() throws Exception { // File file = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test.txt"); File file_copy1 = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test_copy.txt"); // File file_copy1 = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/cat_copy.jpg"); FileInputStream fis = new FileInputStream(testTxt); FileOutputStream fos = new FileOutputStream(file_copy1); //byte[] bytes = new byte[1024]; byte[] bytes = new byte[fis.available()]; int read = fis.read(bytes); if (read != -1){ fos.write(bytes); } fis.close(); fos.close(); } /** * 字符流 * 使用FileInputStream、FileOutputStream、InputStreamReader、OutputStreamWriter、BufferedReader、BufferedWriter 復(fù)制文件 * * readLine() 不用while的判斷只會(huì)輸出一行。 */ public static void copyByReaderAndWriter1() throws Exception { // File testTxt = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test.txt"); File file_copy2 = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test_copy2.txt"); FileInputStream fis = new FileInputStream(testTxt); FileOutputStream fos = new FileOutputStream(file_copy2); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis)); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(fos)); String line; while ((line = bufferedReader.readLine()) != null){ System.out.println(line); bufferedWriter.write(line); } // 注意: fis、fos要在bufferedWriter、bufferedReader關(guān)閉之后,否則會(huì)報(bào)錯(cuò)! bufferedWriter.close(); bufferedReader.close(); fis.close(); fos.close(); } /** * 字符流 * 使用BufferedReader、BufferedWriter、FileReader、FileWriter復(fù)制文件 * @throws Exception */ public static void copyByReaderAndWriter2() throws Exception{ File file_copy3 = new File("/Users/LiuShihao/IdeaProjects/netty_demo/src/main/resources/test_copy3.txt"); BufferedReader bufferedReader = new BufferedReader(new FileReader(testTxt)); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file_copy3)); //readLine() 每次讀取一行 String line; while ((line = bufferedReader.readLine()) != null){ System.out.println(line); bufferedWriter.write(line); } bufferedWriter.close(); bufferedReader.close(); } }
使用BufferReader類的readLine()方法注意問(wèn)題
BufferReader類的readLine()方法
public String readLine()
:直到程序遇到了換行符或者是對(duì)應(yīng)流的結(jié)束符,該方法才會(huì)認(rèn)為讀到了一行,才會(huì)結(jié)束其阻塞,讓程序繼續(xù)往下執(zhí)行。
注意:讀取到?jīng)]有數(shù)據(jù)時(shí)就返回null(因?yàn)槠渌黵ead()方法當(dāng)讀到?jīng)]有數(shù)據(jù)時(shí)返回-1),而實(shí)際上readLine()是一個(gè)阻塞函數(shù),當(dāng)沒(méi)有數(shù)據(jù)讀取時(shí),就一直會(huì)阻塞在那,而不是返回null。
讀取一個(gè)文本行,通過(guò)下列字符之一即可認(rèn)為某行已終止:換行 ('\n')、回車 ('\r') 或回車后直接跟著換行。
返回:到達(dá)流末尾,就返回null。
注意:當(dāng)循環(huán)讀取文件內(nèi)容時(shí),循環(huán)條件的結(jié)束要注意使用正確。
錯(cuò)誤的使用方式:
String valueString = null; while (bf.readLine()!=null){ //這樣會(huì)造成數(shù)據(jù)丟失,因?yàn)樵谶@里已經(jīng)調(diào)用了readLine()方法,已經(jīng)讀取了一行,下次調(diào)用時(shí),就會(huì)丟失一行。 System.out.println(valueString); }
正確的解決方法:用一個(gè)變量來(lái)接收方法的返回值
String valueString = null; while ((valueString=bf.readLine())!=null){ //通過(guò)變量來(lái)接收數(shù)據(jù),避免數(shù)據(jù)丟失 System.out.println(valueString); }
DataInputStream類的readUTF()方法
readUTF讀取的必須是writeUTF()寫(xiě)下的字符串。即DataOutputStream的 writeUTF(String str)方法配套使用
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java設(shè)計(jì)模式之橋梁(Bridge)模式
這篇文章主要介紹了Java設(shè)計(jì)模式之橋梁(Bridge)模式,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)Java設(shè)計(jì)模式的小伙伴們有很好的幫助,需要的朋友可以參考下2021-05-05Idea報(bào)錯(cuò): A JNI error has occurred的問(wèn)題
這篇文章主要介紹了Idea報(bào)錯(cuò): A JNI error has occurred的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08淺談java中Math.random()與java.util.random()的區(qū)別
下面小編就為大家?guī)?lái)一篇淺談java中Math.random()與java.util.random()的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09Java 創(chuàng)建兩個(gè)線程模擬對(duì)話并交替輸出實(shí)現(xiàn)解析
這篇文章主要介紹了Java 創(chuàng)建兩個(gè)線程模擬對(duì)話并交替輸出實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Java拷貝數(shù)組方法Arrays.copyOf()是地址傳遞的證明實(shí)例
今天小編就為大家分享一篇關(guān)于Java拷貝數(shù)組方法Arrays.copyOf()是地址傳遞的證明實(shí)例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10解決沒(méi)有@RunWith 和 @SpringBootTest注解或失效問(wèn)題
這篇文章主要介紹了解決沒(méi)有@RunWith 和 @SpringBootTest注解或失效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04SpringBoot利用Redis解決海量重復(fù)提交問(wèn)題
本文主要介紹了SpringBoot利用Redis解決海量重復(fù)提交問(wèn)題,介紹了三種常見(jiàn)的解決方案,包括使用Redis計(jì)數(shù)器,使用Redis分布式鎖和使用Redis發(fā)布/訂閱機(jī)制,感興趣的可以了解一下2024-03-03Java實(shí)現(xiàn)各種文件類型轉(zhuǎn)換方式(收藏)
這篇文章主要介紹了Java?各種文件類型轉(zhuǎn)換的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03