在java.io包裏面File類是惟一 一個與文件自己有關的程序處理類,可是File只可以操做文件自己而不可以操做文件的內容,或者說在實際的開發之中IO操做的核心意義在於:輸入與輸出操做。而對於程序而言,輸入與輸出可能來自於不一樣的環境,例如:經過電腦鏈接服務器上進行瀏覽的時候,實際上此時客戶端發出了一個信息,然後服務器接收到此信息以後進行迴應處理。html
對於服務器或者是客戶端而言實際上傳遞的就是一種數據流的處理形式,而所謂的數據流指的就是字節數據。而對於這種流的處理形式在java.io包裏面提供有兩類支持:java
·字節處理流:OutputStream(輸出字節流)、InputStream(輸入字節流);數組
·字符處理流:Writer(輸出字符流)、Reader(輸入字符流);服務器
全部的流操做都應該採用以下統一的步驟進行,下面以文件處理的流程爲例:app
·若是如今要進行的是文件的讀寫操做,則必定要經過File類找到一個文件路徑;ide
·經過字節流或字符流的子類爲父類對象實例化;spa
·利用字節流或字符流中的方法實現數據的輸入與輸出操做;code
·流的操做屬於資源操做,資源操做必須進行關閉處理;htm
字節的數據是以byte類型爲主實現的操做,在進行字節內容輸出的時候可使用OutputStream類完成,這個類的基本定義以下:對象
public abstract class OutputStream extends Object implements Closeable, Flushable
首先能夠發現這個類實現了兩個接口,因而基本的對應關係以下:
Closeable: |
Flushable: |
public interface Closeable extends AutoCloseable {public void close() throws Exception;} |
public interface Flushable{public void flush() throws IOException;} |
OutputStream類定義的是一個公共的輸出操做標準,而在這個操做標準裏面一共定義有三個內容輸出的方法。
No |
方法名稱 |
類型 |
描述 |
01 |
public abstract void write(int b) throws IOException |
普通 |
輸出單個字節數據 |
02 |
public void write(byte[] b) throws IOException |
普通 |
輸出一組字節數據 |
03 |
public void write(byte[] b,int off,int len) throws IOException |
普通 |
輸出部分字節數據 |
可是須要注意的一個核心問題在於:OutputStream類畢竟是一個抽象類,而這個抽象類若是要想得到實例化對象,按照傳統的認識應該經過子類實例的向上轉完成,若是說如今要進行的是文件處理操做,則可使用FileOutputStream子類:
由於最終都須要發生向上轉型的處理關係,因此對於此時的FileOutputStream子類核心的關注點就能夠放在構造方法:
·【覆蓋】構造方法:public FileOutputStream(File file) throws FileNotFoundException;
·【追加】構造方法:public FileOutputStream(File file,boolean append) throws FileNotFoundException;
範例:使用OutputStream類實現內容的輸出
1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.OutputStream; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + 7 File.separator + "mldn.txt"); // 一、指定要操做的文件的路徑 8 if (!file.getParentFile().exists()) { // 文件不存在 9 file.getParentFile().mkdirs() ; // 建立父目錄 10 } 11 OutputStream output = new FileOutputStream(file) ; // 二、經過子類實例化 12 String str = "www.mldn.cn" ; // 要輸出的文件內容 13 output.write(str.getBytes()); // 三、將字符串變爲字節數組並輸出 14 output.close(); // 四、關閉資源 15 } 16 }
本程序是採用了最爲標準的形式實現了輸出的操做處理,而且在總體的處理之中,只是建立了文件的父目錄,可是並無建立文件,而在執行後會發現文件能夠自動幫助用戶建立。另外須要提醒的是,因爲OutputStream子類也屬於AutoCloseable接口子類,因此對於close()方法也能夠簡化使用。
範例:自動關閉處理
1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.IOException; 4 import java.io.OutputStream; 5 public class JavaAPIDemo { 6 public static void main(String[] args) throws Exception { 7 File file = new File("D:" + File.separator + "hello" + File.separator + "pluto.txt"); // 一、指定要操做的文件的路徑 8 if (!file.getParentFile().exists()) { // 文件不存在 9 file.getParentFile().mkdirs(); // 建立父目錄 10 } 11 try (OutputStream output = new FileOutputStream(file, true)) {//true表示追加數據 12 String str = "www.cnblogs.com\r\n"; // 要輸出的文件內容 13 output.write(str.getBytes()); // 三、將字符串變爲字節數組並輸出 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 } 18 }
是否使用自動的關閉取決於項目的總體結構,另外還須要提醒的是,整個的程序裏面最終是輸出了一組的字節數據,可是千萬不要忘記了,OutputStream類之中定義的輸出方法一共有三個。
與OutputStream類對應的一個流就是字節輸入流,InputStream類主要實現的就是字節數據讀取,該類定義以下:
public abstract class InputStream extends Object implements Closeable
在InputStream類裏面定義有以下的幾個核心方法:
No |
方法名稱 |
類型 |
描述 |
01 |
public abstract int read() throws IOException |
普通 |
讀取單個字節數據,若是如今已經讀取到底,則返回-1 |
02 |
public int read(byte[] b) throws IOException |
普通 |
讀取一組字節數據,返回的是讀取的個數,若是沒有數據已經讀取到底則返回-1 |
03 |
public int read(byte[] b,int off,int len) throws IOException |
普通 |
讀取一組字節數據(只佔數組的部分) |
InputStream類屬於一個抽象類,這時應該依靠它的子類來實例化對象,若是要從文件讀取必定使用FileInputStream子類,對於子類而言只關心父類對象實例化。
構造方法:public FileInputStream(File file) throws FileNotFoundException;
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.InputStream; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 InputStream input = new FileInputStream(file) ; 8 byte data [] = new byte [1024] ; // 開闢一個緩衝區讀取數據 9 int len = input.read(data) ; // 讀取數據,數據所有保存在字節數組之中,返回讀取個數,若是mldn.txt文件中的長度大於1024則只會讀取到1024字節長度的信息 10 System.out.println("【" + new String(data, 0, len) + "】"); 11 input.close(); 12 } 13 }
對於字節輸入流裏面最爲麻煩的問題就在於:使用read()方法讀取的時候只可以以字節數組爲主進行接收。
特別須要注意的是從JDK1.9開始在InputStream類裏面增長了一個新的方法:public byte[] readAllBytes() throws IOException;
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.InputStream; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 InputStream input = new FileInputStream(file) ; 8 byte data [] = input.readAllBytes() ; // 讀取所有數據 9 System.out.println("【" + new String(data) + "】"); 10 input.close(); 11 } 12 }
若是如今要讀取的內容很大很大的時候,那麼這種讀取直接使程序崩潰。若是要使用盡可能不要超過10KB。
使用OutputStream字節輸出流進行數據輸出的時候使用的都是字節類型的數據,而不少的狀況下字符串的輸出是比較方便的,因此對於java.io包而言,在JDK1.1的時候又推出了字符輸出流:Writer,這個類的定義以下:
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
在Writer類裏面提供有許多的輸出操做方法,重點來看兩個:
·輸出字符數組:public void write(char[] cbuf) throws IOException;
·輸出字符串:public void write(String str) throws IOException;
範例:使用Writer輸出
1 import java.io.File; 2 import java.io.FileWriter; 3 import java.io.Writer; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 if (!file.getParentFile().exists()) { 8 file.getParentFile().mkdirs(); // 父目錄必須存在 9 } 10 Writer out = new FileWriter(file) ; 11 String str = "www.mldn.cn" ; 12 out.write(str); 13 out.close(); 14 } 15 }
使用Writer輸出的最大優點在於能夠直接利用字符串完成。Writer是字符流,字符處理的優點在於中文數據上。
Reader是實現字符輸入流的一種類型,其自己屬於一個抽象類,這個類的定義以下:
public abstract class Reader extends Object implements Readable, Closeable
Reader類裏面並無像Writer類同樣提供有整個字符串的輸入處理操做,只可以利用字符數據來實現接收:
·接收數據:public int read(char[] cbuf) throws IOException;
範例:實現數據讀取
1 import java.io.File; 2 import java.io.FileReader; 3 import java.io.Reader; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 if (file.exists()) { // 文件存在則進行讀取 8 Reader in = new FileReader(file) ; 9 char data[] = new char[1024]; 10 int len = in.read(data) ; 11 System.out.println("讀取內容:" + new String(data,0,len)); 12 in.close(); 13 } 14 } 15 }
字符流讀取的時候只可以按照數組的形式來實現處理操做。
如今經過一系列的分析已經能夠清楚字節流與字符流的基本操做了,可是對於這兩類流依然是存在有區別的,重點來分析一下輸出的處理操做。在使用OutputStream和Writer輸出的最後發現都使用了close()方法進行了關閉處理。
在使用OutputStream類輸出的時候若是沒有使用close()方法關閉輸出流發現內容依然能夠實現正常的輸出,可是若是在使用Writer的時候沒有使用close()方法關閉輸出流,那麼這個時候內容將沒法進行輸出,由於Writer使用到了緩衝區,當使用了close()方法的時候實際上會出現有強制刷新緩衝區的狀況,因此這個時候會將內容進行輸出,若是沒有關閉,那麼將沒法進行輸出操做,因此此時若是在不關閉的狀況下要想將所有的內容輸出可使用flush()方法強制清空。
範例:使用Writer並強制性清空
1 import java.io.File; 2 import java.io.FileWriter; 3 import java.io.Writer; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 if (!file.getParentFile().exists()) { 8 file.getParentFile().mkdirs(); // 父目錄必須存在 9 } 10 Writer out = new FileWriter(file) ; 11 String str = "www.mldn.cn" ; 12 out.write(str); 13 out.flush(); // 強制性刷新 14 } 15 }
問題:能夠修改代碼使out.flush()存在和不存在的區別?查看這二者有什麼區別?
注意:以上例子中的out流不能夠關閉,不然會自動flush()便達不到咱們想要的結果
字節流在進行處理的時候並不會使用到緩衝區,而字符流會使用到緩衝區。另外使用緩衝區的字符流更加適合於進行中文數據的處理,因此在往後的程序開發之中,若是要涉及到包含有中文信息的輸出通常都會使用字符流處理,可是從另一方面來說,字節流和字符流的基本處理形式是類似的,因爲IO不少狀況下都是進行數據的傳輸使用(二進制)因此本次的講解將以字節流爲主。
原文出處:https://www.cnblogs.com/CSAH/p/11774782.html