runes
runes
字符串的Unicode码点(integer Unicode code points
),它公开了字符串的 Unicode 码位。表示Unicode码点的整数。
Runes的含义和获取
使用字符串的runes
属性可以获取该字符串对应的runes表示形式。
const string = 'Dart';
final runes = string.runes.toList();
print(runes); // [68, 97, 114, 116]
const emojiHeart = '♥';
print(emojiHeart.runes); // (9829)
Unicode
为每一个字符、标点符号、表情符号等都定义了一个唯一的数值(即Unicode码点),可以表示任何字符。由于Dart字符串是UTF-16的字符序列,所以在字符串中表达32位的字符序列就需要特殊的语法。
通常使用\uXXXX
的方式来表示Unicode字符, 这里的XXXX
是4个16进制的数, 如,心形符号(♥)的 Unicode 为\u2665
。
对于非4个数值的情况,把编码值放到大括号中即可, 如,笑脸 emoji(😆) 是\u{1f600}
。
const emojiMan = '👨';
const emojiLaughing = '😆';
print(emojiMan.runes); // (128104)
print(emojiLaughing.runes); //(128518)
codeUnits属性可以获取单位Unicode码点
// "Man" emoji ('👨', U+1F468) 由 Surrogate pairs U+d83d and U+dc68 表示。
for (final item in emojiMan.codeUnits) {
print(item.toRadixString(16));
// d83d
// dc68
}
emojiMan.codeUnitAt(idx)
读取指定位置的单位码点。
如何正确读取大于U+FFFF
码点的字符获
超出基本多文种平面(Basic Multilingual Plane (plane 0))的字符,即Unicode码点大于U+FFFF
的字符,使用的是 Surrogate pairs
组合而成。此时查看该字符占用的字符长度为2,比如上面“Man”的emoji '👨'(U+1F468) 由 U+d83d and U+dc68 表示。
下面的'♥'和'😆'都是一个字符,由于码点不同,其长度一个为1,一个为2.
const emojiHeart = '♥';
const emojiLaughing = '😆';
print(emojiHeart.length); // 1
print(emojiLaughing.length); // 2
这就需要正确的读写单个 Unicode 字符:可以使用 characters 包中定义的 characters getter
。如下示例:
import 'package:characters/characters.dart';
void main(){
const emojiHeart = '♥';
const emojiLaughing = '😆';
print('emojiHeart的长度:${emojiHeart.length}');
print('emojiLaughing的长度:${emojiLaughing.length}');
print('emojiHeart索引读取:${emojiHeart[0]}');
print('emojiLaughing索引无法正确读取:${emojiLaughing[0]}');
print('characters读写单个 Unicode 字符:${emojiLaughing.characters.elementAt(0)}');
print('characters读写单个 Unicode 字符:${emojiLaughing.characters.first}');
}
输出:
emojiHeart的长度:1
emojiLaughing的长度:2
emojiHeart索引读取:♥
emojiLaughing索引无法正确读取:�
characters读写单个 Unicode 字符:😆
characters读写单个 Unicode 字符:😆
判断是否应该通过characters读取单个字符【正确读取字符】
const str1='😆Ab12';
const str2='♥Ab123';
// 判断是否是大于 U+FFFF 的码点
if(str1.length==str1.characters.length){
print('str1直接通过索引读写单个字符即可');
}
else{
print('str1需要通过characters读写单个 Unicode 字符');
}
// 判断是否是大于 U+FFFF 的码点
if(str2.length==str2.characters.length){
print('str2直接通过索引读写单个字符即可');
}
else{
print('str2需要通过characters读写单个 Unicode 字符');
}
输出
str1需要通过characters读写单个 Unicode 字符
str2直接通过索引读写单个字符即可
Runes对象的使用——由Unicode码点生成字符或字符串
创建Runes对象,将字符或者字符码点作为参数传递。通过String.fromCharCodes()
方法可以读取Runes对象为字符串,从而实现将字符码点转化为可显示或可输出的字符。
Runes runes = new Runes('\u2665,\u{1f605},\u{1f60e}');
print(runes); // (9829, 44, 128517, 44, 128526)
print(String.fromCharCodes(runes)); // ♥,😅,😎
Symbols
一个Symbol对象代表Dart程序中声明的操作符或者标识符。
也许不会用到Symbol,但是该功能对于通过名字来引用标识符的情况 是非常有价值的,特别是混淆后的代码,标识符的名字被混淆了,但是Symbol的名字不会改变。
可以使用在标识符前加 # 前缀来获取 Symbol:
var radix=10;
var bar='abc';
print(#radix); // Symbol("radix")
print(#bar); // Symbol("bar")