java基礎之IO流(一)
java基礎之IO流(一)之字節流
IO流體系太大,涉及到的各種流對象,我覺得很有必要總結一下。
那什麽是IO流,IO代表Input、Output,而流就是原始數據源與目標媒介的數據傳輸的一種抽象。典型數據源與目標媒介包括磁盤、網絡、內存等等。
IO流的分類:
按流向分為:輸入流和輸出流(本地內存為參考)
按處理數據單位:字符流和字節流
按照是否與特定的地方相連(磁盤、網絡、內存):節點流和處理流
節點流:可以從或向一個特定的地方(節點)讀寫數據。
處理流:是對一個已存在的流的連接和封裝,通過所封裝的流的功能調用實現數據讀寫。
下圖是常用到的IO流,需要說明的是箭頭指向不代表直接的繼承關系。此圖中出現的流還會在下文中一一介紹。
(一)字節流
根據上圖可知,字節流對應的頂層抽象類分別為 InputStream和OutputStream,字節流時萬能流,可以處理任意類型的數據。
InputStream提供了基本的讀取數據的方法:
int read():一次讀取一個字節,返回值為讀到的字節,如果返回值為-1,則表示讀到末端。
int read(byte[] b):一次讀取一個字節數組,返回值為讀到的有效長度。
int read(byte[] b, int offset, int len):一次讀取一個字節數組的一部分(少用),返回值為讀入緩沖區的字節總數,如果讀到末尾,返回-1
其子類就是在三個讀取功能的基礎上進行了各自的實現與功能擴展。
OutputStream提供了基本的寫數據的方法:
void write(int b):一次寫一個字節,形參為int變量,如果b超過了byte的範圍,采取高位截斷的方式進行處理。
void write(byte[] bys):一次寫一個字節數組。
void write(byte[] bys, int offset, int len):一次寫一個字節數組的一部分。
其子類就是在這三個寫功能的基礎上進行各自的實現和功能擴展。
1. FileInputStream和FileOutputStream
從類名中就可以看出這一對輸入輸出流針對的數據源和目標媒介為文件系統。
FIleInputStream:
構造方法有兩個:
FileInputStream(String fileName)和FileInputStream(File file)。
FileInputStream僅僅實現了InputStream提供的基本讀的方法,並沒有特殊的功能。
FileOutputStream:
包含四個構造方法:
FileOutputStream(String fileName) 和FileOutputStream(File file)
FileOutputStream(String fileName,boolean append)和FileOutputStream(File file, boolean append):表示執行寫方法時是否在目標媒介末尾追加。
FileOutputStream一樣,並未對父類功能進行擴展。
2. BufferedInputStream和BufferedOutputStream
自帶緩沖區的字節流,從他的構造方法也可以看出,它是一個處理流,內部封裝了一個InputStream或OutputStream對象。
BuffeedInputStream構造方法:
BufferedInputStream(InputStream in, int size):指定其內部封裝的字節流和緩沖區的大小。
BufferedInputStream(InputStream in, int size):指定內部封裝的字節流,緩沖區的大小采用默認值。
private static int DEFAULT_BUFFER_SIZE = 8192;//默認緩沖區8*1024 protected volatile byte buf[];//實際存放數據的地方
BufferedOutputStream構造參數與BufferedInputStream相同,指定內部的封裝的輸出流和緩沖區大小。
BufferedInputStream和BufferedOutputStream都封裝了節點流,內部維護了一個緩沖區,具體數據的讀寫都是通過傳入的節點流進行的,在讀寫功能上也並未擴展。
3.DataInputStream和DataOutputStream
思考這樣一個問題,操作基本數據類型的數據,若不使用數據流會怎樣?答案是高位階段,造成精度丟失。而數據流(DataInputStream和DataOutputStream)的使命就是完成基本數據類型的讀寫。
它也是一個處理流,內部封裝了節點流,從其構造方法中可以看出:
DataInputStream(InputStream in), 提供了基本數據類型的讀操作:readInt(); readChar();readByte();readBoolean();readDouble()等
DataOutputStream(OutputStream out):包含相應基本數據類型的寫操作。
其讀寫各種數據的內部實現原理也是通過一個一個字節的讀取,然後通過二進制位的移位運算進行的。
需要特別留意的一個方法:
writeUTF() :使用的是修改版的UTF-8編碼:該方法會首先寫入兩個字節用來表示要寫入的字符串的長度,後面跟的是要寫字符串的字節表示,每個字符1~3個字節不等。因此總長度為2+字符串長度到2+字符串長度的3倍不等。readUTF()用於讀取writeUTF寫入的字符串。
4. ByteArrayInputStream和ByteArrayOutputStream
這兩個流是用來臨時處理數據的。
了解ByteArrayOutputStream關鍵一點在於了解它的數據源和目標媒介。數據源很容易理解,就是通過write(int)、write(byte[])、write(byte[] ,int ,int)方法寫入的數據,目標媒介就是內存中的一個字節數組,可自動擴容,內存字節數組的大小可通過構造方法設置,也可使用默認大小。
protected byte buf[];//實際存數據的字節數組 protected int count;//字節數組的有效長度 public ByteArrayOutputStream() { this(32);//默認長度為32 }
ByteArrayInputputStream的數據源是通過構造方法傳入的字節數組,內部也有一個字節數組用於存儲從中讀取的數據。
protected byte buf[]; public ByteArrayInputStream(byte buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length; }
5.PrintStream
PrintStream是用來裝飾其他輸出流,為其他輸出流添加功能,方便他們打印出各種數據值表示形式。與其他輸出流不同,PrintStream永遠不會拋出IOException,它產生的錯誤會被自身的函數所捕獲並設置錯誤標記,用戶可以通過checkError()返回錯誤標記,查看是否產生IOException。PrintStream提供了自動flush和字符集設置功能,寫入的數據會立刻調用flush()函數。PrintStream
打印的所有字符都使用平臺的默認字符編碼轉換為字節,也可通過構造方法設置字符集。
java基礎之IO流(一)