目录

dart:io

dart:io 库提供了用于处理文件、目录、进程、套接字、WebSocket 以及 HTTP 客户端和服务器的 API。

一般来说,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,该 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 类为构建 Web 服务器提供了低级功能。您可以匹配请求处理程序、设置标头、流式传输数据等等。

以下示例 Web 服务器返回简单的文本信息。此服务器侦听端口 8888 和地址 127.0.0.1 (localhost),响应路径 /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 库还为进程套接字Web 套接字提供了 API。有关服务器端和命令行应用程序开发的更多信息,请参阅服务器端 Dart 概述