Dart BytesBuilder
最后修改于 2025 年 4 月 4 日
Dart 中的 BytesBuilder 类提供了一种动态构建字节列表的高效方法。它对于网络协议、文件操作和二进制数据操作非常有用。
BytesBuilder 在内部管理一个可扩展的字节缓冲区,在构建字节序列时最大限度地减少内存分配。它是 Dart dart:typed_data 库的一部分。
基本定义
BytesBuilder 是一个用于构建字节列表的可变集合。它会根据需要自动增长,并提供高效添加字节的方法。
主要功能包括追加操作、长度跟踪和最终字节列表提取。它在构建大型字节序列时尤其高效。
BytesBuilder 的基本用法
此示例展示了使用 BytesBuilder 进行基本字节收集。
import 'dart:typed_data';
void main() {
var builder = BytesBuilder();
builder.addByte(65); // 'A'
builder.addByte(66); // 'B'
builder.addByte(67); // 'C'
var bytes = builder.toBytes();
print(bytes); // [65, 66, 67]
}
我们创建一个 BytesBuilder,添加单个字节,然后提取最终的字节列表。当添加字节时,构建器会在内部处理内存管理。
$ dart main.dart [65, 66, 67]
添加字节列表
此示例演示了一次性添加整个字节列表。
import 'dart:typed_data';
void main() {
var builder = BytesBuilder();
builder.add([1, 2, 3]);
builder.add([4, 5, 6]);
var bytes = builder.toBytes();
print(bytes); // [1, 2, 3, 4, 5, 6]
print('Length: ${builder.length}'); // 6
}
我们添加了多个字节列表,它们会在内部进行连接。length 属性跟踪已添加的总字节数。这比逐个添加字节更有效。
$ dart main.dart [1, 2, 3, 4, 5, 6] Length: 6
构建二进制数据
此示例展示了使用 BytesBuilder 构建结构化二进制数据。
import 'dart:typed_data';
void main() {
var builder = BytesBuilder();
// Add header
builder.add([0xAA, 0xBB]);
// Add payload length (2 bytes)
builder.addByte(0);
builder.addByte(5);
// Add payload
builder.add('Hello'.codeUnits);
// Add checksum
var bytes = builder.toBytes();
var checksum = bytes.fold(0, (sum, byte) => sum + byte) & 0xFF;
builder.addByte(checksum);
print(builder.toBytes());
}
我们使用标头、长度、有效载荷和校验和构建了一个二进制消息。BytesBuilder 高效地处理了混合的数据类型和大小。
$ dart main.dart [170, 187, 0, 5, 72, 101, 108, 108, 111, 142]
清除和重用
此示例演示了如何清除构建器以供重用。
import 'dart:typed_data';
void main() {
var builder = BytesBuilder();
builder.add([1, 2, 3]);
print('First build: ${builder.toBytes()}');
builder.clear();
builder.add([4, 5, 6]);
print('Second build: ${builder.toBytes()}');
print('Capacity: ${builder.length}'); // 3
}
clear() 方法在重用构建器时会重置构建器,同时保留内部容量。这可以避免在重新构建相似大小的字节序列时进行重新分配。
$ dart main.dart First build: [1, 2, 3] Second build: [4, 5, 6] Capacity: 3
性能比较
此示例将 BytesBuilder 与手动列表连接进行了比较。
import 'dart:typed_data';
import 'dart:math';
void main() {
var random = Random();
var data = List.generate(1000, (_) => random.nextInt(256));
// Using BytesBuilder
var stopwatch = Stopwatch()..start();
var builder = BytesBuilder();
for (var i = 0; i < 100; i++) {
builder.add(data);
}
var builderTime = stopwatch.elapsedMicroseconds;
// Using manual concatenation
stopwatch.reset();
var manual = <int>[];
for (var i = 0; i < 100; i++) {
manual = [...manual, ...data];
}
var manualTime = stopwatch.elapsedMicroseconds;
print('BytesBuilder: $builderTime μs');
print('Manual: $manualTime μs');
}
对于大型连接,BytesBuilder 的速度明显更快,因为它最大限度地减少了内存分配和复制。手动连接会创建许多中间列表。
$ dart main.dart BytesBuilder: 1200 μs Manual: 8500 μs
最佳实践
- 预分配:对于已知大小,请使用
initialCapacity构造函数 - 批量添加:对于多个字节,请优先使用 add 而不是 addByte
- 重用:尽可能清除并重用构建器
- 最终确定:仅在需要时调用 toBytes
来源
本教程涵盖了 Dart 的 BytesBuilder 类,并提供了实用示例,展示了基本用法、性能优势以及字节操作的常见模式。
作者
列出 所有 Dart 教程。