您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關JAVA IO體系是怎樣的,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
基于字節的IO操作
基于字符的IO操作
從上圖可以看到,整個Java IO體系都是基于字節流(InputStream/OutputStream) 和 字符流(Reader/Writer)作為基類,根據不同的數據載體或功能派生出來的。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
文件流:FileInputStream/FileOutputStream, FileReader/FileWriter
這四個類是專門操作文件流的,用法高度相似,區別在于前面兩個是操作字節流,后面兩個是操作字符流。它們都會直接操作文件流,直接與OS底層交互。因此他們也被稱為節點流。
注意使用這幾個流的對象之后,需要關閉流對象,因為java垃圾回收器不會主動回收。不過在Java7之后,可以在 try() 括號中打開流,最后程序會自動關閉流對象,不再需要顯示地close。
下面演示這四個流對象的基本用法,
package io; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class TestIO { public static void FileInputStreamTest() throws IOException { FileInputStream fis = new FileInputStream("tmp2.txt"); byte[] buf = new byte[1024]; int hasRead = 0; //read()返回的是單個字節數據(字節數據可以直接專程int類型),但是read(buf)返回的是讀取到的字節數,真正的數據保存在buf中 while ((hasRead = fis.read(buf)) > 0) { //每次最多將1024個字節轉換成字符串,這里tmp2.txt中的字符小于1024,所以一次就讀完了 //循環次數 = 文件字符數 除以 buf長度 System.out.println(new String(buf, 0 ,hasRead)); /* * 將字節強制轉換成字符后逐個輸出,能實現和上面一樣的效果。但是如果源文件是中文的話可能會亂碼 for (byte b : buf) { char ch = (char)b; if (ch != '\r') System.out.print(ch); } */ } //在finally塊里close更安全 fis.close(); } public static void FileReaderTest() throws IOException { try ( // 在try() 中打開的文件, JVM會自動關閉 FileReader fr = new FileReader("tmp2.txt")) { char[] buf = new char[32]; int hasRead = 0; // 每個char都占兩個字節,每個字符或者漢字都是占2個字節,因此無論buf長度為多少,總是能讀取中文字符長度的整數倍,不會亂碼 while ((hasRead = fr.read(buf)) > 0) { // 如果buf的長度大于文件每行的長度,就可以完整輸出每行,否則會斷行。 // 循環次數 = 文件字符數 除以 buf長度 System.out.println(new String(buf, 0, hasRead)); // 跟上面效果一樣 // System.out.println(buf); } } catch (IOException ex) { ex.printStackTrace(); } } public static void FileOutputStreamTest() throws FileNotFoundException, IOException { try ( //在try()中打開文件會在結尾自動關閉 FileInputStream fis = new FileInputStream("tmp2.txt"); FileOutputStream fos = new FileOutputStream("tmp3.txt"); ) { byte[] buf = new byte[4]; int hasRead = 0; while ((hasRead = fis.read(buf)) > 0) { //每讀取一次就寫一次,讀多少就寫多少 fos.write(buf, 0, hasRead); } System.out.println("write success"); } catch (IOException e) { e.printStackTrace(); } } public static void FileWriterTest() throws IOException { try (FileWriter fw = new FileWriter("tmp4.txt")) { fw.write("天王蓋地虎\r\n"); fw.write("寶塔鎮河妖\r\n"); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { //FileInputStreamTest(); //FileReaderTest(); //FileOutputStreamTest(); FileWriterTest(); } }
包裝流:PrintStream/PrintWriter/Scanner
PrintStream可以封裝(包裝)直接與文件交互的節點流對象OutputStream, 使得編程人員可以忽略設備底層的差異,進行一致的IO操作。因此這種流也稱為處理流或者包裝流。
PrintWriter除了可以包裝字節流OutputStream之外,還能包裝字符流Writer
Scanner可以包裝鍵盤輸入,方便地將鍵盤輸入的內容轉換成我們想要的數據類型。
字符串流:StringReader/StringWriter
這兩個操作的是專門操作String字符串的流,其中StringReader能從String中方便地讀取數據并保存到char數組,而StringWriter則將字符串類型的數據寫入到StringBuffer中(因為String不可寫)。
轉換流:InputStreamReader/OutputStreamReader
這兩個類可以將字節流轉換成字符流,被稱為字節流與字符流之間的橋梁。我們經常在讀取鍵盤輸入(System.in)或網絡通信的時候,需要使用這兩個類
緩沖流:BufferedReader/BufferedWriter , BufferedInputStream/BufferedOutputStream
Oracle官方的描述:
Most of the examples we've seen so far use unbuffered I/O. This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient.
Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.
即,
沒有經過Buffered處理的IO, 意味著每一次讀和寫的請求都會由OS底層直接處理,這會導致非常低效的問題。
經過Buffered處理過的輸入流將會從一個buffer內存區域讀取數據,本地API只會在buffer空了之后才會被調用(可能一次調用會填充很多數據進buffer)。
經過Buffered處理過的輸出流將會把數據寫入到buffer中,本地API只會在buffer滿了之后才會被調用。
BufferedReader/BufferedWriter可以將字符流(Reader)包裝成緩沖流,這是最常見用的做法。
另外,BufferedReader提供一個readLine()可以方便地讀取一行,而FileInputStream和FileReader只能讀取一個字節或者一個字符,
因此BufferedReader也被稱為行讀取器
package io; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PushbackReader; import java.io.StringReader; import java.io.StringWriter; public class TestIO { public static void printStream() throws FileNotFoundException, IOException { try ( FileOutputStream fos = new FileOutputStream("tmp.txt"); PrintStream ps = new PrintStream(fos)) { ps.println("普通字符串\n"); //輸出對象 ps.println(new TestIO()); } catch (IOException e) { e.printStackTrace(); } System.out.println("輸出完成"); } public static void stringNode() throws IOException { String str = "天王蓋地虎\n" + "寶塔鎮河妖\n"; char[] buf = new char[32]; int hasRead = 0; //StringReader將以String字符串為節點讀取數據 try (StringReader sr = new StringReader(str)) { while ((hasRead = sr.read(buf)) > 0) { System.out.print(new String(buf, 0, hasRead)); } } catch (IOException e) { e.printStackTrace(); } //由于String是一個不可變類,因此創建StringWriter時,實際上是以一個StringBuffer作為輸出節點 try (StringWriter sw = new StringWriter()) { sw.write("黑夜給了我黑色的眼睛\n"); sw.write("我卻用它尋找光明\n"); //toString()返回sw節點內的數據 System.out.println(sw.toString()); } catch (IOException e) { e.printStackTrace(); } } public static void keyIn() throws IOException { try ( //InputStreamReader是從byte轉成char的橋梁 InputStreamReader reader = new InputStreamReader(System.in); //BufferedReader(Reader in)是char類型輸入的包裝類 BufferedReader br = new BufferedReader(reader); ) { String line = null; while ((line = br.readLine()) != null) { if (line.equals("exit")) { //System.exit(1); break; } System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } public static void pushback() throws FileNotFoundException, IOException { try (PushbackReader pr = new PushbackReader(new FileReader("C:/PROJECT/JavaBasic/PROJECT_JavaBasic/src/io/TestIO.java"),64)) { char[] buf = new char[32]; String lastContent = ""; int hasRead = 0; while ((hasRead = pr.read(buf)) > 0) { String content = new String(buf, 0, hasRead); int targetIndex = 0; if ((targetIndex = (lastContent + content).indexOf("targetIndex = (lastContent + content)")) > 0) { pr.unread((lastContent + content).toCharArray()); if (targetIndex > 32) { buf = new char[targetIndex]; } pr.read(buf , 0 , targetIndex); System.out.println(new String(buf, 0 , targetIndex)); System.exit(0); } else { System.out.println(lastContent); lastContent = content; } } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { printStream(); //stringNode(); //keyIn(); //pushback(); } }
總結上面幾種流的應用場景:
FileInputStream/FileOutputStream 需要逐個字節處理原始二進制流的時候使用,效率低下
FileReader/FileWriter 需要組個字符處理的時候使用
StringReader/StringWriter 需要處理字符串的時候,可以將字符串保存為字符數組
PrintStream/PrintWriter 用來包裝FileOutputStream 對象,方便直接將String字符串寫入文件
Scanner 用來包裝System.in流,很方便地將輸入的String字符串轉換成需要的數據類型
InputStreamReader/OutputStreamReader , 字節和字符的轉換橋梁,在網絡通信或者處理鍵盤輸入的時候用
BufferedReader/BufferedWriter , BufferedInputStream/BufferedOutputStream , 緩沖流用來包裝字節流后者字符流,提升IO性能,BufferedReader還可以方便地讀取一行,簡化編程。
以上就是JAVA IO體系是怎樣的,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。