Java文件和輸入和輸出(I/O)

java.io包幾乎包含了在Java中執行輸入和輸出(I/O)所需的所有類。 所有這些流代表輸入源和輸出目的地。 java.io包中的流支持許多數據,如:原始,對象,本地化字符等。

1. 流(Streams)

流(Streams)可以定義爲數據序列,它有兩種 -

  • InPutStream - 它用於從源讀取數據。
  • OutPutStream - 它用於將數據寫入目標。

Java流

Java爲與文件和網絡相關的I/O提供強大而靈活的支持,但本教程只涵蓋了流和I/O相關的非常基本的功能。下面將看到一些最常用的例子 -

1.1. 字節流
Java字節流用於執行8位字節的輸入和輸出。儘管有許多與字節流相關的類,但最常用的類是FileInputStreamFileOutputStream。以下示例使用這兩個類將輸入文件的內容複製到輸出文件中 -

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 yiibai.com

下一步,編譯上面的程序並執行它,它將創建一個:D:/output.txt文件,內容與D:/input.txt中的相同。

1.2. 字符流

Java字節流用於執行8位字節的輸入和輸出,而Java字符流用於執行16位unicode的輸入和輸出。 儘管有許多與字符流相關的類,但最常用的類是FileReaderFileWriter。 雖然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 yiibai.com

下一步,編譯上面的程序並執行它,它將創建一個:D:/output.txt文件,內容與D:/input.txt中的相同。

2. 標準流

所有編程語言都支持標準I/O,用戶的程序可以從鍵盤輸入,然後在計算機屏幕上產生輸出。 如果您瞭解C或C++編程語言,那麼應該瞭解三個標準流:STDINSTDOUTSTDERR。 同樣,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用於將數據寫入目標。

以下是處理輸入和輸出流的類層次結構。

輸入和輸出流

兩個重要的流是:FileInputStreamFileOutputStream,將在本教程中討論。

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值。

還有其他重要的輸入流可用,有關更多詳細信息,請參閱以下鏈接 -

  • ByteArrayInputStream
  • DataInputStream

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

還有其他重要的輸出流,有關更多詳細信息,請參閱以下鏈接 -

  • ByteArrayOutputStream
  • DataOutputStream

示例

以下是演示如何使用InputStreamOutputStream類對象的示例 -

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的基礎知識。如下 -

  • File類
  • FileReader類
  • FileWriter類

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
... ...