「流」概念源自於UNIX中的管道(pipe)的概念。在UNIX中,管道是一條不間斷的位元組流,用來實現程式或進程間的通信,或讀寫外圍設備、外部文件等,它屏蔽了實際的I/O設備中處理資料的細節。 一個流,必有源端和目的端,它們可以是電腦記憶體的某些區域,也可以是磁碟文件,甚至可以是Internet上的某個URL。 流的方向是重要的,根據流的方向,流可以分為兩類:輸入流和輸出流。其實輸入/輸出是想對於記憶體來說的。實際上,流的源端和目的端可簡單地看成是字節的生產者和消費者,對於輸入流,可不必關心它的源端是什麼,只要簡單地從流中讀數據,而對輸出流,也可不知道它的目的端,只是簡單地往流中寫資料。
a.流:一組有序的資料序列。
b位元組流:資料流中最小的資料單元是位元組。
c.字元流:資料流中最小的資料單元是字元。
一. java.io套件中的類別對應兩類流
一類流直接從指定的位置(如磁碟檔案或記憶體區域)讀取或寫入,這類流稱為結點流,其他的流則稱為過濾流(包裝流)
過濾流:有些流可以從檔案以及其他地方接收字節,有些流可以將位元組組合成更有用的資料類型。將一個已經存在的流傳遞給另一個流的建構方法,將這兩個流結合起來,結合後的流稱為過濾流。過濾器輸入流往往是以其它輸入流作為它的輸入源,經過過濾或處理後再以新的輸入流的形式提供給用戶,過濾器輸出流也類似。我們很少用單一的類別來創建流對象,而是透過疊合多個物件來提供所期望的功能(即裝飾器設計模式)。
java的常用輸入、輸出流其實都是繼承自4個抽象類,分別是:
基於單字節的InputStream,OutputStream類別(位元組形式的I/O)
基於雙位元組的Unicode代碼單元的Reader, Writer類別(面向字元形式的I/O)
一旦開啟輸入流後,程式就可從輸入流串列地讀取資料。從輸入流讀/寫資料的過程一般如下:開啟一個流通道-->讀取/寫資訊-->關閉流通道。
在java平台中,有以下兩種方式能獲得本地平台的字元編碼類型:
(a)System.getProperty("file.encoding");
(b) Charset cs=Charset.defaultCharset();
所有的輸入流、輸出流都可以分成位元組(輸入、輸出)流,字元(輸入、輸出)流,處理位元組的主要是(OutputStream/InputStream) 系列,處理字元的,主要是(Reader/ Write)系列
二.以位元組(Byte)為導向的輸入流(InputStream系列),這幾個類別都可以與FileInputStream物件連接以提供有用介面:
ByteArrayInputStream:把記憶體中的一個緩衝區當作InputStream使用
StringBufferInputStream(在java1.1中已經棄用了):把一個String物件當作InputStream,底層實作使用StringBuffer
FileInputStream:把一個檔案當作InputStream,實作對檔案的讀取操作(檔案名稱、檔案、FileDescriptor物件)
PipedInputStream:實作了pipe的概念,主要在執行緒中使用(作為多進程中的資料來源)
SequenceInputStream:把多個InputStream合併為一個InputStream
以位元組(Byte)為導向的輸出流(OutputStream系列),可以與FilterOutputStream物件連接以提供有用介面:
ByteArrayOutputStream:在記憶體中建立緩衝區,將資訊存入記憶體中的一個緩衝區中,緩衝區初始化尺寸(可選)
FileOutputStream:把資訊存入文件中(檔案名稱、檔案、FileDescriptor)
PipedOutputStream:實作了pipe的概念,主要在執行緒中使用(指定用於多執行緒的資料的目的地)
三.與之對應的(Reader/Writer)系列:
Reader: 與InputStream相對應,適配器InputStreamReader
Writer: 與OutputStream相對應,適配器為OutputStreamWriter
FileReader: 與FileOutputStream相對應
FileWriter: 與FileOurputStream相對應
StringReader: 無相對應的類
StringWriter: 與ByteArrayInputStream相對應
CharArrayReader: 與ByteArrayOutputStream相對應
CharArrayWriter: 與ByteArrayOutputStream相對應
PipedReader: 與PipedInputStream相對應
PipedWriter: 與PipedOutputStream相對應
四.兩種不限導向的stream之間的轉換(使用適配器類別)
InputStreamReader和OutputStreamReader:把以位元組為導向的stream轉換成以字元為導向的stream。
InputStreamReader 是位元組流通向字元流的橋樑:它使用指定的charset 讀取位元組並將其解碼為字元。它使用的字元集可以由名稱指定或明確給定,或者可以接受平台預設的字元集
OutputStreamWriter 是字元流通向位元組流的橋樑:可使用指定的charset 將要寫入流中的字元編碼成位元組。它使用的字元集可以由名稱指定或明確給定,否則將接受平台預設的字元集
五.透過FilterInputStream從InputStream讀取資料:
DataInputStream:從stream讀取基本型別(int、char,長等)資料。
BufferedInputStream:使用緩衝區,使用它可以防止每次讀取都得進行實際的讀取操作
LineNumberInputStream:會記錄input stream內的行數,然後可呼叫getLineNumber()和setLineNumber(int)
PushbackInputStream:很少用到,一般用於編譯器開發
透過FilterOutputStream向OutputStream寫入:
DataIOutputStream:可以依照移植方式在stream中輸出基本類型(int、char,long等)資料。
BufferedOutputStream:使用緩衝區,使用它可避免每次發送資料都進行實際的寫入操作
PrintStream:產生格式化輸出,其中DataOutputStream處理資料的存儲,PrintStream處理顯示
六.更改流的行為
雖然BufferedOutputStream是FilterOutputStream的子類,但是BufferedWriter並不是FilterWriter的子類,(FilterWriter是抽象類,沒有任何子類)
沒有與DataInputStream對應的類別。除非要使用readLine()時改用BufferedReader,否則使用DataInputStream
BufferedReader:與BufferedInputStream對應
LineNumberReader:與LineNumberInputStream對應
PushBackReader:與PushbackInputStream對應
BufferedWrite:與BufferedOutStream對應
PrintWrite:與PrintStream對應
七.自我獨立的類別:RandomAccessFile
這個類別適用於有大小已知的記錄組成的文件,RandomAccessFile除了實作了DataInput和DataOutput介面(DataInputStream和DataOutputStream也實作了這兩個介面)之外,這個類別是個完全獨立的類,它擁有和別的I/O類型本質不同的行為,可以在一個檔案內向前和向後移動,直接從Object派生而來。
可透過RandomAccessFile物件完成對檔案的讀寫操作
在產生一個物件時,可指明要開啟的文件的性質:r,唯讀;w,只寫;rw可讀寫
可以直接跳到文件中指定的位置
RandomAccessFile的大部分功能(不是全部)有nio儲存映射檔案所取代