Java?IO及BufferedReader.readline()出現(xiàn)的Bug
Java IO及BufferedReader.readline()的Bug
IO流

流:流是一組有序的,有起點和終點的字節(jié)集合,是對計算機中數(shù)據(jù)傳輸?shù)目偡Q。即數(shù)據(jù)在兩個設(shè)備間的傳輸稱為流,流的本質(zhì)是數(shù)據(jù)傳輸。
BufferedReader.readline()方法Bug
錯誤代碼:
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é)果控制臺只打印了第二行,最后還報錯了空指針異常
原因:
是代碼中每次調(diào)用readline()方法,就會向下讀取一行所以錯誤代碼中表示的是while 判斷 的第一行不為null,打印的是第二行 ,然后寫入的是第三行,在次while判斷的是第四行 有內(nèi)容,打印的是第五行 為null,寫入的是第六行也為null,就導(dǎo)致了空指針異常。
修改后的代碼:
String line;
while ((line = bufferedReader.readLine()) != null){
System.out.println(line);
bufferedWriter.write(line);
}
結(jié)果:

注意:只用readline()復(fù)制后的但是和原文件是不同,沒有了換行符,如果需要可以在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("開始復(fù)制:"+now);
// copyFile();
// copyByReaderAndWriter1();
copyByReaderAndWriter2();
Instant end = Instant.now();
// Duration 期間Instant Period 時期 LocalDateTime
System.out.println("復(fù)制完成:"+end+",耗時:"+ Duration.between(now,end));
}
/**
* 使用FileinputStream、FileOutputStream 與原文件一樣
* 將一個文件復(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的判斷只會輸出一行。
*/
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)閉之后,否則會報錯!
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()方法注意問題
BufferReader類的readLine()方法
public String readLine():直到程序遇到了換行符或者是對應(yīng)流的結(jié)束符,該方法才會認(rèn)為讀到了一行,才會結(jié)束其阻塞,讓程序繼續(xù)往下執(zhí)行。
注意:讀取到?jīng)]有數(shù)據(jù)時就返回null(因為其它read()方法當(dāng)讀到?jīng)]有數(shù)據(jù)時返回-1),而實際上readLine()是一個阻塞函數(shù),當(dāng)沒有數(shù)據(jù)讀取時,就一直會阻塞在那,而不是返回null。
讀取一個文本行,通過下列字符之一即可認(rèn)為某行已終止:換行 ('\n')、回車 ('\r') 或回車后直接跟著換行。
返回:到達流末尾,就返回null。
注意:當(dāng)循環(huán)讀取文件內(nèi)容時,循環(huán)條件的結(jié)束要注意使用正確。
錯誤的使用方式:
String valueString = null;
while (bf.readLine()!=null){ //這樣會造成數(shù)據(jù)丟失,因為在這里已經(jīng)調(diào)用了readLine()方法,已經(jīng)讀取了一行,下次調(diào)用時,就會丟失一行。
System.out.println(valueString);
}
正確的解決方法:用一個變量來接收方法的返回值
String valueString = null;
while ((valueString=bf.readLine())!=null){ //通過變量來接收數(shù)據(jù),避免數(shù)據(jù)丟失
System.out.println(valueString);
}
DataInputStream類的readUTF()方法
readUTF讀取的必須是writeUTF()寫下的字符串。即DataOutputStream的 writeUTF(String str)方法配套使用
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決try-catch捕獲異常信息后Spring事務(wù)失效的問題
這篇文章主要介紹了解決try-catch捕獲異常信息后Spring事務(wù)失效的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
使用Easyexcel實現(xiàn)不同場景的數(shù)據(jù)導(dǎo)出功能
這篇文章主要為大家詳細介紹了如何在不同場景下使用Easyexcel實現(xiàn)數(shù)據(jù)導(dǎo)出功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
深入分析Android系統(tǒng)中SparseArray的源碼
這篇文章主要介紹了深入分析Android系統(tǒng)中SparseArray的源碼,SparseArray為Java實現(xiàn),需要的朋友可以參考下2015-07-07
SpringMVC使用@Valid注解實現(xiàn)數(shù)據(jù)驗證的代碼示例
在 Web 開發(fā)中,數(shù)據(jù)驗證是一個非常重要的環(huán)節(jié),它可以確保數(shù)據(jù)的合法性和正確性,保護系統(tǒng)不受到惡意攻擊或用戶誤操作的影響,在 SpringMVC 中,我們可以使用 @Valid 注解來實現(xiàn)數(shù)據(jù)驗證,所以本文就給大家介紹具體的使用方法,需要的朋友可以參考下2023-07-07
詳解Spring Boot對 Apache Pulsar的支持
Spring Boot通過提供spring-pulsar和spring-pulsar-reactive自動配置支持Apache Pulsar,類路徑中這些依賴存在時,Spring Boot自動配置命令式和反應(yīng)式Pulsar組件,PulsarClient自動注冊,默認(rèn)連接本地Pulsar實例,感興趣的朋友一起看看吧2024-11-11
Springboot之restTemplate的配置及使用方式
這篇文章主要介紹了Springboot之restTemplate的配置及使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
JVM優(yōu)先級線程池做任務(wù)隊列的實現(xiàn)方法
這篇文章主要介紹了JVM優(yōu)先級線程池做任務(wù)隊列的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
java8新特性之stream的collect實戰(zhàn)教程
這篇文章主要介紹了java8新特性之stream的collect實戰(zhàn)教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08

