java.io包幾乎包含了在Java中執行輸入和輸出(I/O)所需的所有類。 所有這些流代表輸入源和輸出目的地。 java.io包中的流支持許多數據,如:原始,對象,本地化字元等。
1. 流(Streams)
流(Streams)可以定義為數據序列,它有兩種 - 
- InPutStream- 它用於從源讀取數據。
- OutPutStream- 它用於將數據寫入目標。

Java為與檔和網路相關的I/O提供強大而靈活的支持,但本教程只涵蓋了流和I/O相關的非常基本的功能。下麵將看到一些最常用的例子 -
1.1. 位元組流
Java位元組流用於執行8位位元組的輸入和輸出。儘管有許多與位元組流相關的類,但最常用的類是FileInputStream和FileOutputStream。以下示例使用這兩個類將輸入檔的內容複製到輸出檔中 - 
import java.io.*;
public class CopyFile {
   public static void main(String args[]) throws IOException {
      FileInputStream in = null;
      FileOutputStream out = null;
      try {
         in = new FileInputStream("D:\\input.txt");
         out = new FileOutputStream("D:\\output.txt");
         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }
   }
}
假設在D盤下有一個檔:input.txt,它的內容如下 - 
This is test for copy file.
power by xuhuhu.com
下一步,編譯上面的程式並執行它,它將創建一個:D:/output.txt檔,內容與D:/input.txt中的相同。
1.2. 字元流
Java位元組流用於執行8位位元組的輸入和輸出,而Java字元流用於執行16位unicode的輸入和輸出。 儘管有許多與字元流相關的類,但最常用的類是FileReader和FileWriter。 雖然FileReader內部使用FileInputStream類,而FileWriter內部使用FileOutputStream類,但主要區別在於FileReader一次讀取兩個位元組,而FileWriter一次寫入兩個位元組。
可以重新編寫上面的例子,它使用這兩個類將輸入檔(具有unicode字元)複製到輸出檔中 -
import java.io.*;
public class CopyFile {
   public static void main(String args[]) throws IOException {
      FileReader in = null;
      FileWriter out = null;
      try {
         in = new FileReader("D:/input.txt");
         out = new FileWriter("D:/output.txt");
         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }
   }
}
假設在D盤下有一個檔:input.txt,它的內容如下 - 
This is test for copy file.
power by xuhuhu.com
下一步,編譯上面的程式並執行它,它將創建一個:D:/output.txt檔,內容與D:/input.txt中的相同。
2. 標準流
所有編程語言都支持標準I/O,用戶的程式可以從鍵盤輸入,然後在電腦螢幕上產生輸出。 如果您瞭解C或C++編程語言,那麼應該瞭解三個標準流:STDIN,STDOUT和STDERR。 同樣,Java提供以下三個標準流 - 
- 標準輸入 - 用於將數據提供給用戶程式,通常鍵盤用作標準輸入流並表示為System.in。
- 標準輸出 - 用於輸出用戶程式生成的數據,通常電腦螢幕用於標準輸出流並表示為System.out。
- 標準錯誤 - 用於輸出用戶程式生成的錯誤數據,通常電腦螢幕用於標準錯誤流並表示為System.err。
以下是一個簡單的程式,它使用InputStreamReader來讀取標準輸入流,直到用戶鍵入:q - 
import java.io.*;
public class ReadConsole {
   public static void main(String args[]) throws IOException {
      InputStreamReader cin = null;
      try {
         cin = new InputStreamReader(System.in);
         System.out.println("Enter characters, 'q' to quit>");
         char c;
         do {
            c = (char) cin.read();
            System.out.print(c);
         } while(c != 'q');
      }finally {
         if (cin != null) {
            cin.close();
         }
      }
   }
}
將上面的代碼保存在ReadConsole.java檔中,並嘗試編譯並執行它,如下面的程式所示。 程式繼續讀取並輸出用戶輸入的字元,直到按q退出 - 
$javac ReadConsole.java
$java ReadConsole
Enter characters, 'q' to quit>
1
1
a
a
C
C
3. 讀寫檔
如前所述,流可以定義為數據序列。 InputStream用於從源讀取數據,OutputStream用於將數據寫入目標。
以下是處理輸入和輸出流的類層次結構。

兩個重要的流是:FileInputStream和FileOutputStream,將在本教學中討論。
3.1. FileInputStream
此流用於從檔中讀取數據。 可以使用關鍵字new創建對象,並且有幾種類型的構造函數可用。
以下構造函數將檔案名作為字串來創建輸入流對象以讀取檔 -
InputStream f = new FileInputStream("D:/java/hello.txt");
以下構造函數採用檔對象來創建輸入流對象以讀取檔。 首先,使用File()方法創建一個檔對象,如下所示 - 
File f = new File("D:/java/hello.txt");
InputStream f = new FileInputStream(f);
當創建了InputStream對象,就可以使用一些輔助方法來讀取流或在流上執行其他操作。
| 編號 | 方法 | 描述 | 
|---|---|---|
| 1 | public void close() throws IOException{} | 此方法關閉檔輸出流。 釋放與該檔關聯的所有系統資源,拋出 IOException。 | 
| 2 | protected void finalize()throws IOException {} | 此方法清除與檔的連接。 確保在沒有對此流的引用時調用此檔輸出流的 close()方法,拋出IOException。 | 
| 3 | public int read(int r)throws IOException{} | 此方法從 InputStream讀取指定的數據字節,並返回一個int值。 返回數據的下一個位元組,如果它是檔的末尾,則返回-1。 | 
| 4 | public int read(byte[] r) throws IOException{} | 此方法將輸入流中的 r.length個位元組讀入數組。返回讀取的總位元組數。 如果它到達檔的結尾,則返回-1。 | 
| 5 | public int available() throws IOException{} | 給出可以從此檔輸入流中讀取的位元組數。 返回一個 int值。 | 
還有其他重要的輸入流可用,有關更多詳細資訊,請參閱以下鏈接 -
3.2. FileOutputStream
FileOutputStream用於創建檔並將數據寫入檔。 如果檔尚不存在,則會在打開檔以進行輸出之前創建該檔。
這裏有兩個構造函數,可用於創建FileOutputStream對象。
以下構造函數將檔案名作為字串來創建輸入流對象以寫入檔 -
OutputStream f = new FileOutputStream("D:/java/hello.txt")
下麵的構造函數接受一個檔對象來創建一個輸出流對象來寫入該檔。 首先,使用File()方法創建一個檔對象,如下所示 - 
File f = new File("D:/java/hello.txt");
OutputStream f = new FileOutputStream(f);
當創建了OutputStream對象,就使用它的一些輔助方法來寫入流或在流上執行其他操作。
| 編號 | 方法 | 描述 | 
|---|---|---|
| 1 | public void close() throws IOException{} | 此方法關閉檔輸出流,釋放與該檔關聯的所有系統資源。拋出 IOException。 | 
| 2 | protected void finalize()throws IOException {} | 此方法清除與檔的連接,確保在沒有對此流的引用時調用此檔輸出流的 close()方法。拋出IOException。 | 
| 3 | public void write(int w)throws IOException{} | 此方法將指定的位元組寫入輸出流。 | 
| 4 | public void write(byte[] w) | 將長度為 w.length的位元組從位元組數組寫入OutputStream。 | 
還有其他重要的輸出流,有關更多詳細資訊,請參閱以下鏈接 -
示例
以下是演示如何使用InputStream和OutputStream類對象的示例 - 
import java.io.*;
public class fileStreamTest {
   public static void main(String args[]) {
      try {
         byte bWrite [] = {11,21,3,40,5};
         OutputStream os = new FileOutputStream("D:/test.txt");
         for(int x = 0; x < bWrite.length ; x++) {
            os.write( bWrite[x] );   // writes the bytes
         }
         os.close();
         InputStream is = new FileInputStream("D:/test.txt");
         int size = is.available();
         for(int i = 0; i < size; i++) {
            System.out.print((char)is.read() + "  ");
         }
         is.close();
      } catch (IOException e) {
         System.out.print("Exception");
      }
   }
}
上面的代碼將創建檔test.txt並將以二進位格式寫入給定的數字數據,同樣也會在螢幕上輸出。
4. 檔導航和I/O
可通過其他幾個類來瞭解檔導航和I/O的基礎知識。如下 -
4.1. 目錄操作
目錄是一個檔,它可以包含其他檔和目錄的列表。 使用File對象創建目錄,列出目錄中可用的檔。 有關完整的詳細資訊,請查看在File對象上調用的所有方法的列表以及與目錄相關的內容。
4.1.1. 創建目錄
有兩種File類的方法,可用於創建目錄 - 
- mkdir()方法創建一個目錄,創建成功時返回- true,失敗時返回- false。 失敗表示- File對象中指定的路徑已存在,或者由於整個路徑尚不存在或許可權問題而無法創建目錄。
- mkdirs()方法創建目錄和目錄的所有上級目錄。
以下示例創建一個目錄:D:/tmp/user/java/bin -
示例
import java.io.File;
public class CreateDir {
   public static void main(String args[]) {
      String dirname = "D:/tmp/user/java/bin";
      File d = new File(dirname);
      // 創建目錄及父級目錄
      d.mkdirs();
   }
}
編譯並執行上面的代碼來創建目錄:D:/tmp/user/java/bin。
注 - Java會根據約定自動處理UNIX和Windows上的路徑分隔符號。如果在Windows版本的Java上使用正斜杠(/),則路徑仍將正確解析。
4.1.2. 列出目錄
可以使用File對象的list()方法列出目錄中可用的所有檔和目錄,如下所示 - 
import java.io.File;
public class ReadDir {
   public static void main(String[] args) {
      File file = null;
      String[] paths;
      try {
         // 創建一個File對象
         file = new File("D:/software");
         // 檔和目錄的數組
         paths = file.list();
         // 對於路徑數組中的名稱
         for(String path:paths) {
            // 列印檔案名和目錄名
            System.out.println(path);
         }
      } catch (Exception e) {
         // if any error occurs
         e.printStackTrace();
      }
   }
}
執行上面代碼,它將根據D:/software目錄中目錄和文件產生以下結果 - 
apache-maven-3.5.4
apache-tomcat-9.0.14
Aptana_Studio
eclipse
EditPlusPortable
javajars
kafka_2.11-2.0.0
mysql-5.7.23-winx64
Navicat Premium 11
php-cs-fixer.phar
spring-2.0.5.RELEASE
... ...
