原文: characters | Dart Package (flutter-io.cn)
译时版本: 1.2.1
Characters 是可视为 用户感知的字符 序列的字符串,即熟知的 [Unicode (扩展) 字符集]
Characters 类可访问字符串中的单个字符,也提供使用 CharacterRange 在范围内向前和向后导航的方法。
Unicode 字符和表示
这里没有 纯文本 的东西。
计算机只认识数字,所以任何 “文本” 在计算机中都表示为数字,在内存中保存为字节。
这些字节的意思通过解释层提供,编译为计算机显示在屏幕上的象形文字。
| 抽象 | Dart 类型 | 用法 | 示例 |
|---|---|---|---|
| Bytes | ByteBuffer, Uint8List | 物理布局:内存或网络通信。 | file.readAsBytesSync() |
| 码单位 | Uint8List (UTF‑8) Uint16List, String (UTF‑16) | 内存中为码点编码的标准格式。使用 一个字节 (UTF‑8)或 多个字节(UTF‑16)存储在内存中。一个或多个码单位对一个码点进行编码。 | string.codeUnits string.codeUnitAt(index) utf8.encode(string) |
| 码点 | Runes | Unicode 意义上的单位 | string.runes |
| 字符集 | Characters | 人类感知的字符。一个或多个码点 | string.characters |
| 象形文字 | 字符集的可视化渲染。 | print(string) |
一个Dart String 是一个 UTF-16 码单位的序列,就像 JavaScript 和 Java 的字符串。运行时系统依赖底层的物理表示。
当需要操作用户正在查看或输入的文本时,只表示纯字符串是不够的,因为字符串操作不会在字符集级别上进行处理。
例如,要把一段文本缩略为前15个字符或者象形文字,像 "A 🇬🇧 text in English" 这样的字符串,当数字符时会缩略为 "A 🇬🇧 text in Eng… ", 但是如果使用 String 操作数码单位时,就会是 "A 🇬🇧 text in …" 。
无论何时,当需要在字符级别操作字符串时,都就该使用 Characters 类型,而不是使用 String 类的方法。
Characters 类
Characters 类暴露了一个字符串作为字符集的序列。
所有针对 Characters 的操作都是在操作整个字符集,所以它避免了把基于 String 类的固有码单元的合成字符或颜文字分割开的风险。
可以使用 Characters(string) 或扩展的 getter string.characters 获取一个字符串的 Characters 对象。
在它的内核里,该类是一个 Iterable<String> (字符串的迭代器),这里面的元素字符串都是单个字符集。这可以实现按次序读取原始字符串里的单个字符集。
最重要的是,它还有一些 String 操作的一些镜像操作,不是基于索引、码单位或码点的,如 startsWith 或 replaceAll。这些和 String 操作有一些不同。例如, replace 方法只接收字符作为模式。正则表达式不会识别字符集,所以它们不能安全地用于字符序列。
字符集在底层表示上有多种长度,所以对于 Characters 序列的操作不能是基于索引的。
取而代之的是由大大强化的 Characters.iterator提供的 CharacterRange 迭代器 。它可以向前和向后移动,,它能够跨越一个字符集的 范围 。
可用于完整 Characters 的大多数操作也用于字符集的 CharacterRange 范围。
该范围可以多种方式收缩、扩展或移动,而不局限于使用 moveNext 移动到下一个字符集。
例如:
// 使用字符串下标。
String firstTagString(String source) {
var start = string.indexOf("<") + 1;
if (start > 0) {
var end = string.indexOf(">", start);
if (end >= 0) {
return string.substring(start, end);
}
}
return null;
}
// 使用 CharacterRange 操作
Characters firstTagCharacters(Characters source) {
var range = source.findFirst("<".characters);
if (range != null && range.moveUntil(">".characters)) {
return range.currentCharacters;
}
return null;
}