內容

dart:io 函式庫提供 API 來處理檔案、目錄、程序、socket、WebSocket,以及 HTTP 客戶端和伺服器。

一般來說,dart:io 函式庫實作並推廣非同步 API。同步方法很容易會封鎖應用程式,導致難以擴充。因此,大部分操作都透過 Future 或 Stream 物件傳回結果,這是 Node.js 等現代伺服器平台常見的模式。

dart:io 函式庫中少數的同步方法在方法名稱上會清楚標示 Sync 字尾。本文不涵蓋同步方法。

若要使用 dart:io 函式庫,您必須匯入它

dart
import 'dart:io';

檔案和目錄

#

I/O 函式庫讓命令列應用程式可以讀寫檔案和瀏覽目錄。您有兩種選擇可以讀取檔案內容:一次讀取全部,或串流。一次讀取全部檔案需要足夠的記憶體來儲存檔案的所有內容。如果檔案很大,或者您想要在讀取時處理檔案,您應該使用 Stream,如 串流檔案內容 中所述。

以文字讀取檔案

#

當讀取使用 UTF-8 編碼的文字檔案時,您可以使用 readAsString() 讀取整個檔案內容。如果個別行很重要,您可以使用 readAsLines()。在這兩種情況下,都會傳回一個 Future 物件,提供檔案內容作為一個或多個字串。

dart
void main() async {
  var config = File('config.txt');

  // Put the whole file in a single string.
  var stringContents = await config.readAsString();
  print('The file is ${stringContents.length} characters long.');

  // Put each line of the file into its own string.
  var lines = await config.readAsLines();
  print('The file is ${lines.length} lines long.');
}

以二進制讀取檔案

#

以下程式碼將整個檔案讀取為位元組,並儲存在一個整數清單中。呼叫 readAsBytes() 會傳回一個 Future,在結果可用時提供結果。

dart
void main() async {
  var config = File('config.txt');

  var contents = await config.readAsBytes();
  print('The file is ${contents.length} bytes long.');
}

處理錯誤

#

若要擷取錯誤,使其不會導致未捕捉的例外狀況,您可以在 Future 上註冊 catchError 處理常式,或 (在 async 函式中) 使用 try-catch

dart
void main() async {
  var config = File('config.txt');
  try {
    var contents = await config.readAsString();
    print(contents);
  } catch (e) {
    print(e);
  }
}

串流檔案內容

#

使用 Stream 一次讀取檔案的一小部分。您可以使用 Stream APIawait for,這是 Dart 的 非同步支援 的一部分。

dart
import 'dart:io';
import 'dart:convert';

void main() async {
  var config = File('config.txt');
  Stream<List<int>> inputStream = config.openRead();

  var lines = utf8.decoder.bind(inputStream).transform(const LineSplitter());
  try {
    await for (final line in lines) {
      print('Got ${line.length} characters from stream');
    }
    print('file is now closed');
  } catch (e) {
    print(e);
  }
}

寫入檔案內容

#

您可以使用 IOSink 將資料寫入檔案。使用 File openWrite() 方法取得您可以寫入的 IOSink。預設模式 FileMode.write 會完全覆寫檔案中的現有資料。

dart
var logFile = File('log.txt');
var sink = logFile.openWrite();
sink.write('FILE ACCESSED ${DateTime.now()}\n');
await sink.flush();
await sink.close();

若要新增到檔案結尾,請使用選用的 mode 參數指定 FileMode.append

dart
var sink = logFile.openWrite(mode: FileMode.append);

若要寫入二進位資料,請使用 add(List<int> data)

列出目錄中的檔案

#

尋找目錄的所有檔案和子目錄是非同步作業。list() 方法會傳回一個 Stream,在遇到檔案或目錄時發出物件。

dart
void main() async {
  var dir = Directory('tmp');

  try {
    var dirList = dir.list();
    await for (final FileSystemEntity f in dirList) {
      if (f is File) {
        print('Found file ${f.path}');
      } else if (f is Directory) {
        print('Found dir ${f.path}');
      }
    }
  } catch (e) {
    print(e.toString());
  }
}

其他常見功能

#

File 和 Directory 類別包含其他功能,包括但不限於

  • 建立檔案或目錄:File 和 Directory 中的 create()
  • 刪除檔案或目錄:File 和 Directory 中的 delete()
  • 取得檔案長度:File 中的 length()
  • 取得檔案的隨機存取權:File 中的 open()

請參閱 FileDirectory 的 API 文件,以取得方法的完整清單。

HTTP 伺服器和用戶端

#

dart:io 函式庫提供命令列應用程式可使用的類別,用於存取 HTTP 資源,以及執行 HTTP 伺服器。

HTTP 伺服器

#

HttpServer 類別提供用於建置網路伺服器的低階功能。您可以比對要求處理常式、設定標頭、串流資料等等。

以下範例網路伺服器傳回簡單的文字資訊。此伺服器在埠 8888 和位址 127.0.0.1 (本機端) 上監聽,回應路徑 /dart 的要求。對於任何其他路徑,回應是狀態碼 404 (找不到頁面)。

dart
void main() async {
  final requests = await HttpServer.bind('localhost', 8888);
  await for (final request in requests) {
    processRequest(request);
  }
}

void processRequest(HttpRequest request) {
  print('Got request for ${request.uri.path}');
  final response = request.response;
  if (request.uri.path == '/dart') {
    response
      ..headers.contentType = ContentType(
        'text',
        'plain',
      )
      ..write('Hello from the server');
  } else {
    response.statusCode = HttpStatus.notFound;
  }
  response.close();
}

HTTP 用戶端

#

您應該避免直接使用 dart:io 來發出 HTTP 要求。dart:io 中的 HttpClient 類別與平台相關,並繫結到單一實作。請改用較高階的函式庫,例如 package:http

從網際網路擷取資料」教學說明如何使用 package:http 進行 HTTP 要求。

更多資訊

#

此頁面顯示如何使用 dart:io 函式庫的主要功能。除了本節討論的 API 外,dart:io 函式庫還提供 處理程序socketweb socket 的 API。如需關於伺服器端和命令列應用程式開發的更多資訊,請參閱 伺服器端 Dart 概觀