JDK1.0輸入流
InputStream |
ByteArrayInputStream |
FileInputStream |
FilterInputStream |
ObjectInputStream |
PipedInputStream |
SequenceInputStream |
|
BufferedInputStream |
DataInputStream |
PushbackInputStream |
LineNumberInputStream |
JDK1.1輸入流
Reader |
BufferedReader |
FilterReader |
PipedReader |
StringReader |
InputStreamReader |
CharArrayReader |
FileReader |
PushbackReader |
LineNumberReader |
JDK1.0輸出流
OutputStream |
BufferedOutputStream |
DataOutputStream |
PrintStream |
ByteArrayOutputStream |
FileOutputStream |
FilterOutputStream |
ObjectOutputStream |
PipedOutputStream |
JDK1.1輸出流
Writer |
BufferedWriter |
FilterWriter |
PipedWriter |
StringWriter |
FileWriter |
PrintWriter |
OutputStreamWriter |
CharArrayWriter
|
如果你剛剛接觸Java的IO部分, 你可能會感覺無從入手, 確實Java提供了過多的類,反而讓人感到很亂。
可將Java庫的IO類分為輸入與輸出兩個部分, 在1.0版本中提供了兩個抽象基類, 所有輸入的類都從InputStream繼承, 所有輸出的類都從OutputStream繼承, 1.1提供了兩個新的基類, 負責輸入的Reader與輸出的Writer, 但它們並不是用來替換原來老的InputStream與OutputStream, 它們主要是讓Java能更好的支持國際化的需求。 原來老的IO流層隻支持8位字節流, 不能很好地控製16位Unicode字符。 Java內含的char是16位的Unicode, 所以添加了Reader和Writer層次以提供對所有IO操作中的Unicode的支持。 除此之外新庫也對速度進行了優化, 可比舊庫更快地運行。
InputStream的類型:
1. 字節數組
2. String對象
3. 文件
4. 管道, 可以從另外一個輸出流得到一個輸入流
5. 一係列的其他流, 可以將這些流統一收集到單獨的一個流內。
6. 其他起源(如socket流等)
還有一個是File類, Java中一個目錄也是一個文件,可以用file.isFile()和file.isDirectory()來進行判斷是文件還是目錄。 File 對象可能作為參數轉換為文件流進行操作。 具體操作參照Java IO API。
常用方法:
/**
* 拚文件名, 在windows(\)跟unix(/)上的文件分割符是不一樣的
* 可以通過File類的靜態成員變量separator取得
*/
public static String concatFileName(String dir, String fileName) {
String fullFileName = "";
if (dir.endsWith(File.separator)) {fullFileName = dir + fileName;
} else {fullFileName = dir + File.separator + fileName;}
return fullFileName; }
/**
* 從控製台讀取輸入的數據, System.in (InputStream) 先轉換至InputStreamReader再用
* BufferedReader進行讀取.
*
*/
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String str = "";
while (str != null) {str = in.readLine();// process(str); }
/**
* 從文件中按行進行讀取數據處理
*/
BufferedReader in = new BufferedReader(new FileReader("infilename"));
String str;
while ((str = in.readLine()) != null) {// process(str); }
in.close();
/**
* 寫數據至一個新的文件中去.
*/
BufferedWriter out = new BufferedWriter(new FileWriter("outfilename"));
out.write("a String");
out.close();
/**
* 追加新的數據到一個文件中去, 如果原文件不存在
* 則新建這個文件.
*/
BufferedWriter out = new BufferedWriter(new FileWriter("filename", true));
out.write("aString");
out.close();
/**
* 將一個可序列化的Java的object以流方式寫到一個文件中去中.
*/
ObjectOutput out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
out.writeObject(object);
out.close();
/**
* 從文件中恢複序列化過的Java Object
*/
ObjectInputStream in = new ObjectInputStream(new FileInputStream("filename.ser"));
Object object = (Object) in.readObject();
in.close();
/**
* 以指定的編碼方式從文件中讀取數據
*/
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream("infilename"), "UTF8"));
String str = in.readLine();
/**
* 以指定的編碼方式寫數據到文件中
*/
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("outfilename"), "UTF8"));
out.write("a String");
out.close();
由上麵的例子可以看出, 流之間可以互相轉換, 如果想對流進行字符操作最好將之轉換成BufferedReader與BufferedWriter這樣可以提高讀寫的效率。
需要注意的是一般來說流的大小是得不到的, 雖然一般的InputStream都有一個available()的方法可以返回這個流可以讀到的字節數, 不過這個方法有時候不會很準確, 比如在讀取網絡傳輸的流的時候, 取到的長度並不一定是真實有效的長度。
大家在寫程序的時候可能已經注意到一些類都繼承了java.io.Serializable這個接口, 其實繼承了這個接口之後這個類的本身並不做任何事情, 隻是這個類可以被序列化並通過流來進行傳輸, 並可被還原成原Object。 這個流可以通過網絡傳輸(EJB 中進行傳遞參數和返回值的Data Class), 也可以保存到文件中去(ObjectOutputStream)。