ZetCode

Dart ReadPipe

最后修改于 2025 年 4 月 4 日

Dart 中的 ReadPipe 类提供了一种从流中读取数据的有效方法。它对于处理连续数据源(如网络套接字或文件)非常有用。

ReadPipe 在内部管理流订阅和数据缓冲,简化了流的消耗。它是 Dart 异步编程模型的一部分,用于处理 I/O 操作。

基本定义

ReadPipe 是一个实用类,用于以块(chunks)的形式从流中读取数据。它同时提供了同步和异步数据读取模式的方法。

主要功能包括缓冲读取、流管理和灵活的数据消费。它在处理大量数据流方面特别高效。

ReadPipe 的基本用法

本示例展示了 ReadPipe 的基本流读取用法。

main.dart
import 'dart:async';
import 'dart:io';

Future<void> main() async {
  var pipe = ReadPipe(Stream.fromIterable(['Hello', ' ', 'World']));
  
  var data = await pipe.read();
  print(data); // 'Hello World'
}

我们从一个简单的流创建一个 ReadPipe,并读取所有可用数据。该管道会自动处理流订阅和数据收集。

$ dart main.dart
Hello World

分块读取

本示例演示了以固定大小的块读取流数据。

main.dart
import 'dart:async';

Future<void> main() async {
  var stream = Stream.fromIterable(['Dart', ' ', 'is', ' ', 'awesome!']);
  var pipe = ReadPipe(stream);
  
  while (true) {
    var chunk = await pipe.readBytes(3);
    if (chunk.isEmpty) break;
    print('Chunk: $chunk');
  }
}

我们以 3 字节的块读取流。该管道会在读取之间缓冲数据,并自动处理不完整的块。这对于固定大小的协议很有用。

$ dart main.dart
Chunk: Dar
Chunk: t i
Chunk: s a
Chunk: wes
Chunk: ome
Chunk: !

处理二进制数据

本示例展示了如何从文件流中读取二进制数据。

main.dart
import 'dart:async';
import 'dart:io';

Future<void> main() async {
  var file = File('data.bin');
  var pipe = ReadPipe(file.openRead());
  
  var header = await pipe.readBytes(4);
  print('Header: $header');
  
  var body = await pipe.read();
  print('Body length: ${body.length} bytes');
}

我们使用 ReadPipe 读取一个二进制文件,首先提取一个 4 字节的头部,然后读取剩余内容。该管道高效地处理了字节流。

$ dart main.dart
Header: [137, 80, 78, 71]
Body length: 1024 bytes

错误处理

本示例演示了 ReadPipe 的错误处理。

main.dart
import 'dart:async';

Future<void> main() async {
  var controller = StreamController();
  var pipe = ReadPipe(controller.stream);
  
  controller.add('Data');
  controller.addError('Stream error');
  
  try {
    await pipe.read();
  } catch (e) {
    print('Error: $e');
  } finally {
    await controller.close();
  }
}

我们模拟了一个流错误,并展示了 ReadPipe 如何将流错误传播给读取器。适当的错误处理对于健壮的流处理至关重要。

$ dart main.dart
Error: Stream error

与 Transformer 结合使用

本示例展示了 ReadPipe 与流 Transformer 的用法。

main.dart
import 'dart:async';
import 'dart:convert';

Future<void> main() async {
  var stream = Stream.fromIterable(['{"name":', ' "John", "age": 30}']);
  var jsonStream = stream.transform(utf8.decoder).transform(json.decoder);
  var pipe = ReadPipe(jsonStream);
  
  var data = await pipe.read();
  print('Name: ${data['name']}');
  print('Age: ${data['age']}');
}

我们将 ReadPipe 与 JSON 解码 Transformer 一起使用。该管道可以与转换后的流无缝协作,使复杂的处理管道更容易实现。

$ dart main.dart
Name: John
Age: 30

最佳实践

来源

Dart ReadPipe 文档

本教程通过实际示例介绍了 Dart 的 ReadPipe 类,展示了基本用法、错误处理以及与流 Transformer 的集成。

作者

我叫 Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 Dart 教程