風蕭蕭兮易水寒,串流一去兮不復還

I/O 以連接的節點(Node)、傳送的資料型態、以及輸入/輸出來區分

分作以下類別(Class)

檔案
記憶體
Pipe
 X  位元組(Byte)傳輸
字元(char)傳輸
字串(String)傳輸
 X 
輸入
輸出

通常做位元組傳輸,會叫做Stream

以常見的字串傳輸,會叫做Reader/Writer

舉例來說,FileInputStream是做檔案位元輸入的類別;InputStreamReader是做字串輸入的類別

Pipe是比較特殊的用途,搭配在多執行續上使用,參照PipedInputStreamPipedOutputStream

字串處理的I/O被分離在ReaderWriter類別底下

其他的都直接繼承了InputStreamOutputStream

 

不論是哪一種傳輸,都是以節點(Node)做為起點或終點,做出Stream這樣的動作

Stream就如同字面上的意思,像水流一樣,有開有關

當Read()或write()方法被呼叫時,串流就會開啟,直到close()被呼叫為止

有時候串流會有保護同時只開放一個程序使用,因此必須記得close()串流,避免其他程序無法使用

 

在文章的第一行就有提到,串流是無法回頭的

當一直Read()資料時,串流就一點一點的流去,不會回頭

不過如果一定要讓流過的串流再回頭看一次,就要使用一些Buffer的方式,先把串流存起來,就像是蓄水槽一樣

JAVA也有提供一些搭配使用的緩衝區類別,等一下會說到

 

通常我們會用到的串流,就是以檔案為節點的串流了,讀寫檔案都用的到

使用的方法十分簡單,只需要開檔後,建立起Stream的物件,在使用讀寫的方法就可以了

✎ 記事本                      _  ❒   1.在想要的目錄中建立一個文字檔
This is a test...



import java.io.*;

public class Test {
public static void main(String[] args) {
FileInputStream fin;
try {
fin = new FileInputStream("c:\\file.txt");
while (fin.available() > 0)
System.out.print(fin.read());
} catch (IOException e) {
e.printStackTrace();
}
}
}


 2.使用程式碼來讀檔
◙ C:\Windows\System32\cmd.exe         _  ❒ 
 3.執行的結果,很容易吧
This is a test...


前面有提到,FileInputStream他是以Byte為傳輸單位

而英文字母和一般標點符號長度也恰好是一個Byte,因此顯示出來都很正常

不過如果讀寫中文時就會出問題了

✎ 記事本                     _  ❒   1.這次的內容是中文
中文測試




◙ C:\Windows\System32\cmd.exe        _  ❒ 
 2.執行結果
出現了世界末日的日期 (誤
164164164229180250184213



如果想要順利的讀取中文,又想堅持使用FileInputStream的話,就要用到Byte[] 來做buffer,而且陣列大小必須是2的倍數,因為中文字佔2個Byte


import java.io.*;


public class Test {
public static void main(String[] args) {
FileInputStream fin;
try {
fin = new FileInputStream("c:\\file.txt");
byte buf[] = new byte[8];//建立一個大小8Byte的緩衝區
int bufSize;//用來計算讀入的資料大小
while (fin.available() > 0)
bufSize = fin.read(buf);//讀取資料到buf內
System.out.print(new String(buf, 0, bufSize));

} catch (IOException e) {
e.printStackTrace();
}
}
}


 1.修改一些程式碼
◙ C:\Windows\System32\cmd.exe        _  ❒ 
        2.出現了正確的結果
中文測試



不過要是中文字中間夾雜了1Byte大小的字元,讀取就會錯亂,這時候就沒有辦法再堅持使用FileInputStream了

FileReader就登場了!


import java.io.*;


public class Test {
public static void main(String[] args) {
FileReader fin;
try {
fin = new FileReader("c:\\file.txt");
int word;
while (fin.ready()){
word = fin.read();
System.out.print((char)word);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

跟FileInputStream幾乎是一樣的用法

FileReader或FileWriter都是以字元做傳輸的單位,因此不管是中文還是英文,都可以正常的傳輸

 

到這裡為止,我們知道要如何讀寫檔案文字

但是如果我們要讀寫的是數字、浮點數甚至是物件呢?

當然你可以把123或者0.01還有其他資料用String的方式寫到檔案中,就像剛才那樣

不過如此寫入的話,取出時,還要做字串分析等等繁雜的工作

雖然不是不可以,但是程式就不漂亮了

那麼,該如何把真正的"資料型態"寫到檔案裡面呢?

我們需要一些轉接頭,把資料型態與串流做個連結,稱作chain

為了達到串流連結,我們要用到一些的類別,也就是轉接頭,稱作Filter

Filter除了可以達到轉換型態的功能外,還有些具有緩衝的功能,也就是讓流去的串流可以被回朔

來看看JAVA提供那些Filter的類別

串流緩衝區 BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter

物件串流 ObjectInputStream
ObjectOutputStream
基本資料型態串流 InputStreamReader
InputStreamWriter
DataInputStream
DataOutputStream

計算行數 LineNumberInputStream
LineNumberReader
堆疊串流 PushbackInputStream
PushbackReader
列印串流 PrintStream
PrintWriter
藍色的比較常用喔

 

這麼多種類轉接頭,看到都暈了…

不過常用的也不會很多,拿比較常用的DataOutputStream舉例吧

DataOutputStream可以將輸出的資料轉換成各種基本資料型態:int, char, double, float...等等

要怎麼轉呢?看看↓


import java.io.*;


public class Test {
public static void main(String[] args) {
FileOutputStream fin;
try {
fin = new FileOutputStream("c:\\file.txt");
DataOutputStream dataWrite = new DataOutputStream(fin);
short sh[] = {1,2,3,4,5};
for(short i : sh){
dataWrite.writeShort(i);//這裡的方法要搭配資料型態使用
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

這樣就完成了寫入short資料型態的數字到檔案裡了,當然也可以用類似方式寫入整數、浮點數等等…

不過當好奇的用記事本打開檔案一看…奇怪,啥都沒有啊!

那是當然的了,因為那不是以"字串"的編碼寫入,而是以你指定的資料編碼寫入(上面例子就是short)

而記事本只會把資料以字串的編碼來呈現,其中字串編碼又分ASCII、UTF…數種

不過當你再寫一段以short讀入資料的程式之後,你就可以直接用short的變數來接收讀入的資料了

超方便的!

 

剛才有提到,除了基本資料型態之外,物件也可以存進檔案中

不過存進去的只限於"資料",也就是物件中的"屬性(attribute)"

物件中的方法(method)是不會被存的

物件在要被丟到串流中之前,必須先序列化(Serialization),序列化其實也不是甚麼很神祕的東西,只是把資料從物件中抽出來準備傳送而已,這個部分電腦會幫你完成,你只需要在你想要被傳送的類別上,implements Serializable就可以了

用到的Filter類別是ObjectInputStream、ObjectOutputStream,用法跟基本資料型態的一樣,把FileOutputStream的物件掛上去(傳入建構子)就可以了

同樣的,讀取物件時,用該物件來接收,你就可以得到之前存起來的物件了

arrow
arrow

    yaya741228 發表在 痞客邦 留言(2) 人氣()