dart:io
dart:io 庫提供了處理檔案、目錄、程序、套接字、WebSocket 以及 HTTP 客戶端和伺服器的 API。
通常,dart:io 庫實現並推廣了非同步 API。同步方法很容易阻塞應用程式,使其難以擴充套件。因此,大多數操作透過 Future 或 Stream 物件返回結果,這是一種與 Node.js 等現代伺服器平臺常見的模式。
dart:io 庫中少數同步方法在其方法名稱上帶有明確的 Sync 字尾標記。此處不涵蓋同步方法。
要使用 dart:io 庫,您必須匯入它
import 'dart:io';檔案和目錄
#I/O 庫使命令列應用能夠讀寫檔案和瀏覽目錄。讀取檔案內容有兩種選擇:一次性讀取,或流式讀取。一次性讀取檔案需要足夠的記憶體來儲存檔案的所有內容。如果檔案非常大或者您想在讀取時處理它,則應使用 Stream,如流式傳輸檔案內容中所述。
按文字讀取檔案
#讀取使用 UTF-8 編碼的文字檔案時,可以使用 readAsString() 讀取整個檔案內容。如果單獨的行很重要,可以使用 readAsLines()。在這兩種情況下,都會返回一個 Future 物件,該物件提供檔案內容作為一條或多條字串。
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,當結果可用時,它會提供結果。
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
void main() async {
var config = File('config.txt');
try {
var contents = await config.readAsString();
print(contents);
} catch (e) {
print(e);
}
}流式傳輸檔案內容
#使用 Stream 每次讀取檔案的一小部分。您可以使用Stream API 或 await for,這是 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 會完全覆蓋檔案中已有的資料。
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
var sink = logFile.openWrite(mode: FileMode.append);要寫入二進位制資料,請使用 add(List<int> data)。
列出目錄中的檔案
#查詢目錄中的所有檔案和子目錄是一個非同步操作。list() 方法返回一個 Stream,當遇到檔案或目錄時,它會發出一個物件。
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()方法
有關完整的方法列表,請參閱 File 和 Directory 的 API 文件。
HTTP 客戶端和伺服器
#dart:io 庫提供了一些類,命令列應用可以使用它們來訪問 HTTP 資源以及執行 HTTP 伺服器。
HTTP 伺服器
#使用 HttpServer 類提供了構建 Web 伺服器的低階功能。您可以匹配請求處理程式、設定標頭、流式傳輸資料等。
以下是返回簡單文字資訊的 Web 伺服器示例。該伺服器監聽 8888 埠和地址 127.0.0.1 (localhost),響應對路徑 /dart 的請求。對於任何其他路徑,響應的狀態碼為 404(頁面未找到)。
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 庫還提供了用於程序、套接字和Web 套接字的 API。有關伺服器端和命令列應用開發的更多資訊,請參閱伺服器端 Dart 概覽。