likes
comments
collection
share

[Flutter]足够入门的Dart语言系列之正确认识和解读Runes与Symbols类型

作者站长头像
站长
· 阅读数 109

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")

参考

转载自:https://juejin.cn/post/7147247885107593253
评论
请登录