1. 程式人生 > >Java 輸入/輸出流

Java 輸入/輸出流

1. 編碼問題

在介紹輸入輸出之前我們先介紹下關於編碼的一些基本知識點,當一個檔案中既有中文字元又有英文字元時,他們在不同的編碼方式下會佔據不同的記憶體:
1. ANSI 中文佔據 2 個位元組的記憶體空間,英文佔據 1 個位元組的記憶體空間。
2. GBK 中文佔據 2 個位元組的記憶體空間,英文佔據 1 個位元組的記憶體空間。
3. UTF-8 中文佔據 3 個位元組的記憶體空間,英文佔據 1 個位元組的記憶體空間。
4. UTF-16Be 中文佔據 2 個位元組的記憶體空間,英文佔據 2 位元組的記憶體空間。

JAVA 內建使用的是雙位元組編碼,也就是 UTF-16BE。

2. File 類

java.io.File 類用於表示檔案(或目錄)

File 類只用於表示檔案(或目錄)的資訊(名稱、大小等),不能用於檔案內容的訪問。

File 類的構造方法:

File(File parent, String child);//根據 parent 抽象路徑名和 child 路徑名字串建立一個新 File 例項。 
File(String pathname); //通過將給定路徑名字串轉換為抽象路徑名來建立一個新 File 例項。 
File(String parent, String child);//根據 parent 路徑名字串和 child 路徑名字串建立一個新 File 例項。 
File(URI uri);//通過將給定的 file: URI 轉換為一個抽象路徑名來建立一個新的 File 例項。

關於 File 類的一些其他方法我們可查閱 API 文件。

3. RandomAccessFile 類

RandomAccessFile 是 java 提供的對檔案內容的訪問,既可以讀檔案,也可以寫檔案。

RandomAccessFile 類的例項支援對隨機訪問檔案的讀取和寫入,可以訪問檔案的任意位置。隨機訪問檔案的行為類似儲存在檔案系統中的一個大型 byte 陣列。存在指向該隱含陣列的游標或索引,稱為檔案指標;輸入操作從檔案指標開始讀取位元組,並隨著對位元組的讀取而前移此檔案指標。如果隨機訪問檔案以讀取/寫入模式建立,則輸出操作也可用;輸出操作從檔案指標開始寫入位元組,並隨著對位元組的寫入而前移此檔案指標。寫入隱含陣列的當前末尾之後的輸出操作導致該陣列擴充套件。該檔案指標可以通過 getFilePointer 方法讀取,並通過 seek 方法設定。
通常,如果此類中的所有讀取例程在讀取所需數量的位元組之前已到達檔案末尾,則丟擲 EOFException(是一種 IOException)。如果由於某些原因無法讀取任何位元組,而不是在讀取所需數量的位元組之前已到達檔案末尾,則丟擲 IOException,而不是 EOFException。需要特別指出的是,如果流已被關閉,則可能丟擲 IOException。

構造方法:

RandomAccessFile(File file, String mode);//建立從中讀取和向其中寫入(可選)的隨機訪問檔案流,該檔案由 File 引數指定。 
RandomAccessFile(String name, String mode);//建立從中讀取和向其中寫入(可選)的隨機訪問檔案流,該檔案具有指定名稱。 

其中 mode 主要有兩種模式,”rw”(讀寫) 和 “r”(只讀)。

該類還分別提供了一個寫入方法和讀方法:
write(int): 只寫一個位元組(後8位),同時指標指向下一個位置,準備再次寫入
raf.read(): 讀一個位元組

4. 位元組流

提供位元組流讀取方式的類主要有 InputStream 類和 OutputStream 類及其子類。
InputStream 抽象類是表示位元組輸入流的所有類的超類,OutputStream 抽象類是表示位元組輸出流的所有類的超類。
InputStream 的子類主要有:
- FileInputStream
- FilterInputStream (其下有 BufferedInputStream、DataInputStream 和 PushbackInputStream 三個子類)
- ObjectInputStream
- PipedInputStream
- SequenceInputStream
- StringBufferInputStream
- ByteArrayInputStream

OutputStream 的子類主要有:
- FileOutputStream
- FilterOutputStream (其下有 BufferedOutputStream、DataOutputStream 和 PrintStream 三個子類)
- ObjectOutputStream
- PipedOutputStream
- ByteArrayOutputStream

主要子類的介紹:
FileInputStream: 具體實現了在檔案上讀取資料
FileOutputStream: 實現了向檔案中寫出byte資料的方法
DataOutputStream/DataInputStream: 對”流”功能的擴充套件,可以更加方面的讀取int,long,字元等型別資料
BufferedInputStream/BufferedOutputStream: 這兩個流類位IO提供了帶緩衝區的操作,一般開啟檔案進行寫入或讀取操作時,都會加上緩衝,這種流模式提高了IO的效能
如果從應用程式中把輸入放入檔案,相當於將一缸水倒入到另一個缸中,那麼:
FileOutputStream —> write() 方法相當於一滴一滴地把水“轉移”過去
DataOutputStream –> writeXxx() 方法會方便一些,相當於一瓢一瓢把水“轉移”過去
BufferedOutputStream —> write 方法更方便,相當於一飄一瓢先放入桶中,再從桶中倒入到另一個缸中,效能提高了

FileInputStream 和 FileOutputStream 類的主要方法:

//FileInputStream 類
int read() ;// 從此輸入流中讀取一個數據位元組 
int read(byte[] b);  //從此輸入流中將最多 b.length 個位元組的資料讀入一個 byte 陣列中,返回實際讀取的位元組的個數 
int read(byte[] b, int off, int len);  //從此輸入流中將最多 len 個位元組的資料讀入一個 byte 陣列中,返回實際讀取的位元組的個數 
long skip(long n); //從輸入流中跳過並丟棄 n 個位元組的資料 
//FileOutputStream 類
void write(byte[] b); //將 b.length 個位元組從指定 byte 陣列寫入此檔案輸出流中 
void write(byte[] b, int off, int len);  //將指定 byte 陣列中從偏移量 off 開始的 len 個位元組寫入此檔案輸出流
void write(int b);  //將指定位元組寫入此檔案輸出流。 

DataInputStream 和 DataOutputStream 類的主要方法:

//DataInputStream 類
int read(byte[] b);  //從包含的輸入流中讀取一定數量的位元組,並將它們儲存到緩衝區陣列 b 中
int read(byte[] b, int off, int len); //從包含的輸入流中將最多 len 個位元組讀入一個 byte 陣列中
boolean readBoolean(); //讀取一個輸入位元組,如果該位元組不是零,則返回 true,如果是零,則返回 false 
char readChar();  //讀取兩個輸入位元組並返回一個 char 值
double readDouble(); //讀取八個輸入位元組並返回一個 double 值
void readFully(byte[] b); //從輸入流中讀取一些位元組,並將它們儲存在緩衝區陣列 b 中
void readFully(byte[] b, int off, int len);  //從輸入流中讀取 len 個位元組
//DataOutputStream 類
write(byte[] b, int off, int len); //將指定 byte 陣列中從偏移量 off 開始的 len 個位元組寫入基礎輸出流
void write(int b);  //將指定位元組(引數 b 的八個低位)寫入基礎輸出流
void writeBoolean(boolean v); //將一個 boolean 值以 1-byte 值形式寫入基礎輸出流
void writeChars(String s);   //將字串按字元順序寫入基礎輸出流
void writeDouble(double v); //使用 Double 類中的 doubleToLongBits 方法將 double 引數轉換為一個 long 值,然後將該 long 值以 8-byte 值形式寫入基礎輸出流中,先寫入高位元組
void writeInt(int v);  //將一個 int 值以 4-byte 值形式寫入基礎輸出流中,先寫入高位元組  
void writeUTF(String str); /以與機器無關方式使用 UTF-8 修改版編碼將一個字串寫入基礎輸出流
//更多方法可參見API

BufferedInputStream 和 BufferedOutputStream 類的主要方法:

//BufferedInputStream類
void mark(int readlimit);  //在此輸入流中標記當前的位置
boolean markSupported();   //測試此輸入流是否支援 mark 和 reset 方法
int read(byte[] b); //從輸入流中讀取一定數量的位元組,並將其儲存在緩衝區陣列 b 中
int read(byte[] b, int off, int len);   //將輸入流中最多 len 個數據位元組讀入 byte 陣列 
void reset();    //將此流重新定位到最後一次對此輸入流呼叫 mark 方法時的位置
long skip(long n);  //跳過和丟棄此輸入流中資料的 n 個位元組
//BufferedOutputStream 類
void flush();  //重新整理此緩衝的輸出流
void write(byte[] b, int off, int len);  //將指定 byte 陣列中從偏移量 off 開始的 len 個位元組寫入此緩衝的輸出流
void write(int b);  //將指定的位元組寫入此緩衝的輸出流

5. 字元流

字元流(Reader Writer)操作的是文字文字檔案,一次處理一個字元,字元的底層任然是基本的位元組序列。

提供字元流讀取方式的類主要有 Reader 類和 Writer 類及其子類。

Reader 的子類主要有:
- BufferedReader
- InputStreamReader(及其還包含 FileReader 子類)
- StringReader
- PipedReader
- ByteArrayReader
- FilterReader(及其還包含 PushbackReader 子類)

Writer 的子類主要有:
- BufferedWriter
- OutputStreamWriter(及其還包含 FileWriter 子類)
- StringWriter
- PipedWriter
- CharArrayWriter
- FilterWriter
- PrinterWriter

BufferedReader 和 BufferedWriter 類的主要方法:

//BufferedReader
int read(); //讀取單個字元
int read(char[] cbuf, int off, int len); //將字元讀入陣列的某一部分 
String readLine(); //讀取一個文字行
long skip(long n); //跳過字元
//BufferedWriter
void flush();   //重新整理該流的緩衝
void newLine();  //寫入一個行分隔符
void write(char[] cbuf, int off, int len); //寫入字元陣列的某一部分
void write(int c);  //寫入單個字元
void write(String s, int off, int len);  //寫入字串的某一部分 

FileReader 和 FileWriter 類的主要方法:

//FileReader
int read(); 讀取單個字元
int read(char[] cbuf, int offset, int length); 將字元讀入陣列中的某一部分
//FileWriter
void flush();  //重新整理該流的緩衝
String getEncoding(); //返回此流使用的字元編碼的名稱
void write(char[] cbuf, int off, int len);  //寫入字元陣列的某一部分 
void write(int c);   //寫入單個字元