程式設計語言的I/O類庫中常常使用流這個抽象的概念,它代表任何有能力產生資料的資料來源對象或時有能力接收資料的接收端對象。“流”概念源於UNIX中的管道(pipe)的概念。在UNIX中,管道是一條不間斷的位元組流,用來實現程式或進程間的通訊,或讀寫外圍裝置、外部檔案等,它屏蔽了實際的I/O裝置中處理資料的細節。 一個流,必有源端和目的端,它們可以是電腦記憶體的某些地區,也可以是磁碟檔案,甚至可以是Internet上的某個URL。 流的方向是重要的,根據流的方向,流可以分為兩類:輸入資料流和輸出資料流。其實輸入/輸出是想對於記憶體來說的。
實際上,流的源端和目的端可簡單地看成是位元組的生產者和消費者,對於輸入資料流,可不必關心它的源端是什麼,只要簡單地從流中讀資料,而對輸出資料流,也可不知道它的目的端,只是簡單地往流中寫資料。
1: a.流:一組有序的資料序列。
2: b.位元組流:資料流中最小的資料單元是位元組。
3: 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對象相連以提供有用介面:
1) ByteArrayInputStream:把記憶體中的一個緩衝區作為InputStream使用
2) StringBufferInputStream(
在java1.1中已經棄用了
):把一個String對象作為InputStream,底層實現使用StringBuffer
3) FileInputStream:把一個檔案作為InputStream,實現對檔案的讀取操作(檔案名稱、檔案、FileDescriptor對象)
4) PipedInputStream:實現了pipe的概念,主要線上程中使用(作為多進程中的資料來源)
5) SequenceInputStream:把多個InputStream合并為一個InputStream
以位元組(Byte)為導向的輸出資料流(OutputStream系列),可以與FilterOutputStream對象相連以提供有用介面:
1) ByteArrayOutputStream:在記憶體中建立緩衝區,把資訊存入記憶體中的一個緩衝區中,緩衝區初始化尺寸(可選)
2) FileOutputStream:把資訊存入檔案中(檔案名稱、檔案、FileDescriptor)
3) PipedOutputStream:實現了pipe的概念,主要線上程中使用(指定用於多線程的資料的目的地)
三。與之對應的(Reader/Writer)系列:
1: Reader: 與InputStream相對應,適配器InputStreamReader
2: Writer: 與OutputStream相對應,適配器為OutputStreamWriter
3: FileReader: 與FileOutputStream相對應
4: FileWriter: 與FileOurputStream相對應
5: StringReader: 無相對應的類
6: StringWriter: 與ByteArrayInputStream相對應
7: CharArrayReader: 與ByteArrayOutputStream相對應
8: CharArrayWriter: 與ByteArrayOutputStream相對應
9: PipedReader: 與PipedInputStream相對應
10: PipedWriter: 與PipedOutputStream相對應
四。兩種不限導向的stream之間的轉換(使用適配器類)
InputStreamReader和OutputStreamReader:把一個以位元組為導向的stream轉換成一個以字元為導向的stream。
InputStreamReader 是位元組流通向字元流的橋樑:它使用指定的 charset 讀取位元組並將其解碼為字元。它使用的字元集可以由名稱指定或顯式給定,或者可以接受平台預設的字元集
OutputStreamWriter 是字元流通向位元組流的橋樑:可使用指定的 charset 將要寫入流中的字元編碼成位元組。它使用的字元集可以由名稱指定或顯式給定,否則將接受平台預設的字元集
五。通過FilterInputStream從InputStream讀取資料:
1) DataInputStream:從stream中讀取基本類型(int、char,long等)資料。
2) BufferedInputStream:使用緩衝區 ,使用它可以防止每次讀取都得進行實際的讀操作
3) LineNumberInputStream:會記錄input stream內的行數,然後可調用getLineNumber()和setLineNumber(int)
4) PushbackInputStream:很少用到,一般用於編譯器開發
通過FilterOutputStream向OutputStream寫入:
1) DataIOutputStream:可以按照移植方式往stream中輸出基本類型(int、char,long等)資料。
2) BufferedOutputStream:使用緩衝區 ,使用它可避免每次發送資料都進行實際的寫操作
3) PrintStream:產生格式化輸出 ,其中DataOutputStream處理資料的儲存,PrintStream處理顯示
六。更改流的行為:
儘管BufferedOutputStream是FilterOutputStream的子類,但是BufferedWriter並不是FilterWriter的子類,(FilterWriter是抽象類別,沒有任何子類)
1) 沒有與DataInputStream對應的類。除非在要使用readLine()時改用BufferedReader,否則使用DataInputStream
2) BufferedReader:與BufferedInputStream對應
3) LineNumberReader:與LineNumberInputStream對應
4) PushBackReader:與PushbackInputStream對應
5) BufferedWrite:與BufferedOutStream對應
6) PrintWrite:與 PrintStream對應
七。自我獨立的類:RandomAccessFile:
這個類適用於有大小已知的記錄組成的檔案,RandomAccessFile除了實現了DataInput和DataOutput介面(DataInputStream和DataOutputStream也實現了這兩個介面)之外,這個類是個完全獨立的類,它擁有和別的I/O類型本質不同的行為,可以在一個檔案內向前和向後移動,直接從Object派生而來。
1) 可通過RandomAccessFile對象完成對檔案的讀寫操作
2) 在產生一個對象時,可指明要開啟的檔案的性質:r,唯讀;w,唯寫;rw可讀寫
3) 可以直接跳到檔案中指定的位置
RandomAccessFile的大部分功能(不是全部)有nio儲存對應檔所取代八.I/O流的典型使用方式:1。緩衝輸入檔案
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class BufferedInputFile { public static String read(String filename) throws IOException{BufferedReader in=new BufferedReader(new FileReader(filename));String s;StringBuilder sb=new StringBuilder();while((s=in.readLine())!=null){ sb.append(s+"\n");}in.close();return sb.toString();} public static void main(String[] args) throws IOException {System.out.println(read("C:\\Users\\wubin\\workspace\\Imp\\src\\no9\\BufferedInputFile.java"));}}2。從記憶體輸入
import java.io.IOException;import java.io.StringReader;public class MemoryTest {public static void main(String[] args) throws IOException {StringReader in=new StringReader(BufferedInputFile.read("C:\\Users\\wubin\\workspace\\Imp\\src\\no9\\BufferedInputFile.java"));int c;while((c=in.read())!=-1)System.out.print((char)c);}}3。格式化的記憶體輸入
import java.io.ByteArrayInputStream;import java.io.DataInputStream;import java.io.IOException;public class FormattedMemoryInput {public static void main(String[] args) throws IOException{try{DataInputStream in=new DataInputStream(new ByteArrayInputStream(BufferedInputFile.read("C:\\Users\\wubin\\workspace\\Imp\\src\\no9\\BufferedInputFile.java").getBytes()));while(true)System.out.print((char)in.readByte());}catch(Exception e){}}}
import java.io.BufferedInputStream;import java.io.DataInputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class TestEOF {public static void main(String[] args) throws IOException {DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream("C:\\Users\\wubin\\workspace\\Imp\\src\\no9\\BufferedInputFile.java")));while(in.available()!=0)System.out.print((char)in.readByte());}}4。基本檔案輸出
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter;import java.io.StringReader;public class BasicFileOutput {static String file="E:\\2.txt";public static void main(String[] args) throws IOException {BufferedReader in=new BufferedReader(new StringReader(BufferedInputFile.read("E:\\1.txt")));PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter(file)));int cout=1;String s;while((s=in.readLine())!=null)out.println(cout++ +" "+s); out.close();System.out.println(BufferedInputFile.read(file));}}5。儲存和恢複資料
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class StoringAndRecoveringData {public static void main(String[] args) throws IOException{DataOutputStream out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream("E:\\1.txt")));out.writeUTF("hello");out.writeDouble(1.23);out.writeInt(3); out.close();DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream("E:\\1.txt")));System.out.println(in.readUTF());System.out.println(in.readDouble());System.out.println(in.readInt());}}6。讀寫隨機訪問檔案
import java.io.IOException;import java.io.RandomAccessFile;public class UsingRandomAccessFile {static String file="E:\\1.txt";static void display() throws IOException{RandomAccessFile rf=new RandomAccessFile(file,"r");for(int i=0;i<7;i++)System.out.println("Value "+i+": "+rf.readDouble());System.out.println(rf.readUTF());rf.close();} public static void main(String[] args) throws IOException{RandomAccessFile rf=new RandomAccessFile(file,"rw");for(int i=0;i<7;i++)rf.writeDouble(i*1.414);rf.writeUTF("The end of the file");rf.close();display();rf=new RandomAccessFile(file,"rw");rf.seek(5*8);rf.writeDouble(42.0001);rf.close();display();}}
PipedInputStream,PipedOutputStream,PipedReader和PipedWriter的價值體現在多線程上(管道流用於任務之間的通訊)