Java - 檔案和I/O



java.io 包包含幾乎所有在 Java 中執行輸入和輸出 (I/O) 可能需要的類。所有這些流都代表一個輸入源和一個輸出目標。java.io 包中的流支援許多資料,例如基本型別、物件、本地化字元等。

流可以定義為一系列資料。有兩種型別的流:

  • InputStream - InputStream 用於從源讀取資料。

  • OutputStream - OutputStream 用於將資料寫入目標。

Streams

Java 提供了強大而靈活的支援,用於與檔案和網路相關的 I/O,但本教程涵蓋了與流和 I/O 相關的非常基本的功能。我們將一一檢視最常用的示例:

位元組流

Java 位元組流用於執行 8 位位元組的輸入和輸出。儘管有很多與位元組流相關的類,但最常用的類是FileInputStreamFileOutputStream。以下是一個使用這兩個類將輸入檔案複製到輸出檔案的示例:

示例

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile {

   public static void main(String args[]) throws IOException {  
      FileInputStream in = null;
      FileOutputStream out = null;

      try {
         in = new FileInputStream("input.txt");
         out = new FileOutputStream("output.txt");
         
         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }
   }
}

現在讓我們有一個名為input.txt的檔案,其內容如下:

This is test for copy file.

下一步,編譯上述程式並執行它,這將導致建立一個 output.txt 檔案,其內容與 input.txt 中的內容相同。所以讓我們將上述程式碼放在 CopyFile.java 檔案中並執行以下操作:

$javac CopyFile.java
$java CopyFile

字元流

Java 位元組流用於執行 8 位位元組的輸入和輸出,而 Java 字元流用於執行 16 位 Unicode 的輸入和輸出。儘管有很多與字元流相關的類,但最常用的類是FileReaderFileWriter。雖然 FileReader 在內部使用 FileInputStream,FileWriter 使用 FileOutputStream,但這裡的區別在於 FileReader 一次讀取兩個位元組,FileWriter 一次寫入兩個位元組。

我們可以重寫上面的示例,該示例使用這兩個類將輸入檔案(包含 Unicode 字元)複製到輸出檔案:

示例

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyFile {

   public static void main(String args[]) throws IOException {
      FileReader in = null;
      FileWriter out = null;

      try {
         in = new FileReader("input.txt");
         out = new FileWriter("output.txt");
         
         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }
   }
}

現在讓我們有一個名為input.txt的檔案,其內容如下:

This is test for copy file.

下一步,編譯上述程式並執行它,這將導致建立一個 output.txt 檔案,其內容與 input.txt 中的內容相同。所以讓我們將上述程式碼放在 CopyFile.java 檔案中並執行以下操作:

$javac CopyFile.java
$java CopyFile

標準流

所有程式語言都提供對標準 I/O 的支援,使用者程式可以從鍵盤接收輸入,然後在計算機螢幕上產生輸出。如果您瞭解 C 或 C++ 程式語言,那麼您一定了解三個標準裝置 STDIN、STDOUT 和 STDERR。類似地,Java 提供以下三個標準流:

  • 標準輸入 - 用於向用戶程式提供資料,通常使用鍵盤作為標準輸入流,表示為System.in

  • 標準輸出 - 用於輸出使用者程式產生的資料,通常使用計算機螢幕作為標準輸出流,表示為System.out

  • 標準錯誤 - 用於輸出使用者程式產生的錯誤資料,通常使用計算機螢幕作為標準錯誤流,表示為System.err

以下是一個簡單的程式,它建立一個InputStreamReader來讀取標準輸入流,直到使用者輸入“q”:

示例

import java.io.InputStreamReader;
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
e
e
q
q

讀取和寫入檔案

如前所述,流可以定義為一系列資料。InputStream 用於從源讀取資料,OutputStream 用於將資料寫入目標。

這是一個處理輸入和輸出流的類層次結構。

Files IO

兩個重要的流是FileInputStreamFileOutputStream,本教程將討論它們。

FileInputStream

此流用於從檔案讀取資料。可以使用關鍵字new建立物件,並且有多種型別的建構函式可用。

以下建構函式採用檔名作為字串,以建立一個輸入流物件來讀取檔案:

InputStream f = new FileInputStream("C:/java/hello");

以下建構函式採用檔案物件來建立一個輸入流物件以讀取檔案。首先,我們使用 File() 方法建立一個檔案物件,如下所示:

File f = new File("C:/java/hello");
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。

還有其他重要的輸入流可用,更多詳細資訊,您可以參考以下連結:

FileOutputStream

FileOutputStream 用於建立檔案並將資料寫入其中。如果檔案尚不存在,則流會在開啟檔案進行輸出之前建立該檔案。

以下是可以用來建立 FileOutputStream 物件的兩個建構函式。

以下建構函式採用檔名作為字串,以建立一個輸入流物件來寫入檔案:

OutputStream f = new FileOutputStream("C:/java/hello") 

以下建構函式採用檔案物件來建立一個輸出流物件以寫入檔案。首先,我們使用 File() 方法建立一個檔案物件,如下所示:

File f = new File("C:/java/hello");
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.OutputStream;

public class fileStreamTest {

   public static void main(String args[]) {
   
      try {
         byte bWrite [] = {11,21,3,40,5};
         OutputStream os = new FileOutputStream("test.txt");
         for(int x = 0; x < bWrite.length ; x++) {
            os.write( bWrite[x] );   // writes the bytes
         }
         os.close();
     
         InputStream is = new FileInputStream("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 並以二進位制格式寫入給定的數字。標準輸出螢幕上的輸出也將相同。

檔案導航和I/O

還有其他幾個類我們將學習,以瞭解檔案導航和 I/O 的基礎知識。

Java 中的目錄

目錄是一個 File,它可以包含其他檔案和目錄的列表。您可以使用File 物件來建立目錄,列出目錄中可用的檔案。有關完整詳細資訊,請檢視可以在 File 物件上呼叫的所有方法的列表以及與目錄相關的那些方法。

建立目錄

有兩個有用的File 實用程式方法,可用於建立目錄:

  • mkdir( ) 方法建立一個目錄,成功時返回 true,失敗時返回 false。失敗表示 File 物件中指定的路徑已存在,或者由於整個路徑尚不存在而無法建立目錄。

  • mkdirs() 方法建立目錄及其所有父目錄。

以下示例建立 "/tmp/user/java/bin" 目錄:

示例

import java.io.File;

public class CreateDir {

   public static void main(String args[]) {
      String dirname = "/tmp/user/java/bin";
      File d = new File(dirname);
      
      // Create directory now.
      d.mkdirs();
   }
}

編譯並執行上述程式碼以建立 "/tmp/user/java/bin"。

注意 - Java 會根據約定自動處理 UNIX 和 Windows 上的路徑分隔符。如果您在 Windows 版本的 Java 上使用正斜槓 (/),路徑仍然可以正確解析。

列出目錄

您可以使用File 物件提供的list( ) 方法列出目錄中可用的所有檔案和目錄,如下所示:

示例

import java.io.File;

public class ReadDir {

   public static void main(String[] args) {
      File file = null;
      String[] paths;
  
      try {      
         // create new file object
         file = new File("/tmp");

         // array of files and directory
         paths = file.list();

         // for each name in the path array
         for(String path:paths) {
            // prints filename and directory name
            System.out.println(path);
         }
      } catch (Exception e) {
         // if any error occurs
         e.printStackTrace();
      }
   }
}

這將根據/tmp 目錄中可用的目錄和檔案產生以下結果:

輸出

test1.txt
test2.txt
ReadDir.java
ReadDir.class
廣告
© . All rights reserved.