本文已参与「新人创作礼」活动,一起开启创作之路。

这是【Dart 教程系列第 32 篇】,如果觉得有用的话,欢迎关注专栏。

Dart 中的 String 编码格式是 UTF-16,也就是 16 位的 Unicode 转换格式的代码单元序列。

以 Dart SDK 2.13.4 版本为例,Dart 中关于字符串的方法有 25 个,本篇博客说下其中的 23 个,因为有两个过于冷门,不再进行说明,接下来我将按字符串的功能来逐个介绍相应的方法。

一:字符串类型转换

toString

源码如下所示

external String toString();

语法

在 Dart 中继承于 Object 的类型,都支持一个方法那就是 toString(),该方法可以将目标类型转换为 String 类型。

举例

int a = 10;
print(a.toString()); // int 类型的 10 转换为 String 类型的 "10"
List list = [1, 3, 5];
print(list.toString()); // List 数组类型 [1, 3, 5] 转换为 String 类型的 "[1, 3, 5]"
Map map = {"name": "Allen Su", "age": 18};
print(map.toString()); // Map 字典类型转换为 String 类型的 "{"name": "Allen Su", "age": 18}"

其它类型比如 double、num、Set 等的转换也是一样的。


二:字符串查找

indexOf

源码如下所示

int indexOf(Pattern pattern, [int start = 0]);

语法

由前向后查找指定字符,返回值是 int 类型,如果有符合条件的则返回对应字符所在的索引,没有找到则返回 -1。

第一个参数是要查找的字符,支持正则表达式,后面如果看到 Pattern 类型的,都可以用正则表达式代替字符。

第二个为可选参数,从哪个索引处开始查找(包括该索引),默认为 0 ,其中 start 不能为负数,且不大于被查找字符的串长度。

举例

String text = "abcDcbaE";
// 01 查找字符 c 第一次出现时的索引
print(text.indexOf('c')); // 返回 2
// 02 从索引 3 位置开始查找字符 c 第一次出现时的索引
print(text.indexOf('c', 3)); // 返回 4
// 03 查找字符 p 第一次出现时的索引
print(text.indexOf('p')); // // 返回 -1
// 04 使用正则表达式,查找第一次出现大写字母的字符时的索引
print(text.indexOf(RegExp('[A-Z]'))); // 返回 3

lastIndexOf

源码如下所示

int lastIndexOf(Pattern pattern, [int? start]);

语法

由后向前查找指定字符,返回值是 int 类型,如果有符合条件的则返回对应字符所在的索引,没有找到则返回 -1。需要事先说明的一点,倒序查找不是说索引也倒过来了。

第一个参数是要查找的字符,第二个为可选参数,从哪个索引处开始查找(包括该索引),没有默认值。

举例

String text = "abcDcbaE";
// 01 倒序查找字符 a 第一次出现时的索引
print(text.lastIndexOf('a')); // 返回 6
// 02 从索引 2 位置倒序查找字符 a 第一次出现时的索引
print(text.lastIndexOf('a', 2)); // 返回 0
// 03 倒序查找字符 p 第一次出现时的索引
print(text.lastIndexOf('p')); // 返回 -1
// 04 使用正则表达式,倒序查找第一次出现大写字母的字符时的索引
print(text.lastIndexOf(RegExp('[A-Z]'))); // 返回 7

三:字符串判断

contains

源码如下所示

bool contains(Pattern other, [int startIndex = 0]);

语法

判断字符串中是否包含指定字符,存在返回 true,不存在返回 false。

第一个参数是指定的字符,第二个为可选参数,代表从哪个索引位置开始判断,默认为 0 ,其中 startIndex 不能为负数,且不大于字符串的长度。

举例

String text = "https://allensu.blog.csdn.net";
// 01 判断字符串中是否包含字符 allensu
print(text.contains('allensu')); // 返回 true
// 02 判断字符串中是否包含字符 CSDN
print(text.contains('CSDN')); // 返回 false
// 03 判断从索引 8 位置处开始,字符串中是否包含字符 /
print(text.contains('/', 8)); // 返回 false

startsWith

源码如下所示

bool startsWith(Pattern pattern, [int index = 0]);

语法

判断字符串是否以指定字符开头,成立返回 true,不成立返回 false。

第一个参数是指定的字符,第二个为可选参数,代表从哪个索引位置开始判断,默认为 0 ,其中 index 不能为负数,且不大于字符串的长度。

举例

String text = "https://allensu.blog.csdn.net";
// 01 判断字符串是否以字符 https 开头
print(text.startsWith('https')); // 返回 true
// 02 判断字符串是否以字符 w 开头
print(text.startsWith('w')); // 返回 false
// 03 判断从索引 6 位置处开始,字符串是否以字符 // 开头
print(text.startsWith('//', 6)); // 返回 true

endsWith

源码如下所示

bool endsWith(String other);

语法

判断字符串是否以指定字符结尾,成立返回 true,不成立返回 false,参数 other 为指定的字符。

举例

String text = "https://allensu.blog.csdn.net";
// 01 判断字符串是否以字符 net 结尾
print(text.endsWith('net')); // 返回 true
// 02 判断字符串是否以字符 w 结尾
print(text.endsWith('w')); // 返回 false

四:字符串分割

substring

源码如下所示

String substring(int start, [int? end]);

语法

第一个参数 start 是开始分割字符串的索引,当只传了 start 参数时,表示从 start 索引处截取到字符串末尾。

第二个参数 end 是可选参数,表示结束分割字符串的索引,end 的值不能大于字符串的长度。

字符串截取的范围是 [start,end),也就是含头不含尾。

举例

String text = "aaabbbccc";
// 01 从索引 3 位置到末尾,分割字符串
print(text.substring(3)); // 返回 bbbccc
// 02 从索引 3 位置到索引 8 位置,分割字符串
print(text.substring(3, 8)); // 返回 bbbcc

split

源码如下所示

List<String> split(Pattern pattern);

语法

以指定字符分割字符串,返回类型为 List<String> ,被分割的字符不会添加到数组中。

如果指定的分割字符不在字符串中,则将整个字符串直接添加到数组中,作为新数组中的一个元素。

举例

// 01 以字符 % 分割字符串
String str1 = "a%b%c%d%e%f";
List<String> l1 = str1.split('%');
print(l1); // 返回长度为 6 的字符串列表 [a, b, c, d, e, f]
// 02 以空格分割字符串
String str2 = "abcdef";
List<String> l2 = str2.split('');
print(l2); // 返回长度为 6 的字符串列表 [a, b, c, d, e, f]
// 03 当指定的字符不在字符串中时
String str3 = "xyz";
List<String> l3 = str3.split('+');
print(l3); // 返回 [xyz]

splitMapJoin

源码如下所示

String splitMapJoin(
  Pattern pattern, {
  String Function(Match)? onMatch,
  String Function(String)? onNonMatch,
});

语法

这个方法比较特殊,可以在一条语句中完成 3 件事,虽然我平常用到的不多,但还是要知道这个方法的用途。

第一个参数可以是一个字符串 String 或一个正则 RegExp 对象。

第二个参数是可选参数,表示将每个和指定的分割字符匹配的,替换为自定义返回的字符串。

第三个参数也是可选参数,但和第二个参数刚好相反,表示将每个和指定的分割字符不匹配的,替换为自定义返回的字符串。

举例

String text = "a,b,c,d";
String val = text.splitMapJoin(
  ',', // 以逗号 , 为分割字符
  onMatch: (Match match) => "y", // 将字符串中是逗号的替换为字符 y
  onNonMatch: (String nonMatch) => "x", // 将字符串中不是逗号的替换为字符 x
);
print(val); // 返回 xyxyxyx

五:字符串转换大小写

toUpperCase

源码如下所示

String toUpperCase();

语法

将字符串中所有的小写字母转换为大写字母,已是大写字母或者不是小写字母的如数字,返回原字符。

举例

String text = "abcDe123";
print(text.toUpperCase()); // 返回 ABCDE123

toLowerCase

源码如下所示

String toLowerCase();

语法

将字符串中所有的大写字母转换为小写字母,已是小写字母或者不是大写字母的如数字,返回原字符。

举例

String text = "123AbCdE";
print(text.toLowerCase()); // 返回 123abcde

六:字符串补齐

padLeft

源码如下所示

String padLeft(int width, [String padding = ' ']);

语法

字符串左补齐,指定 width 后,如果有剩余位则使用指定字符替换。如果指定 width 小于字符串长度,则返回原字符串。

第一个参数 width 不是补齐后的字符串总长度,你可以用 width 减去原来字符串的长度,得到的结果表示将会在字符串左边添加多少个补齐的字符(见下面的 01、02、03 例子)

第二个参数 padding 为可选参数,表示要补齐的字符,不指定时默认补上空格。

举例

String text = "5";
// 01 在指定字符串左边,添加 (4-text.length=3) 个空格至原来的字符串
print(text.padLeft(4)); // 返回 "   5",注意,字符 5 左边有三个空格
// 02 在指定字符串左边,添加 (4-text.length=3) 个字符 2 至原来的字符串
print(text.padLeft(4, '2')); // 返回 2225
// 03 在指定字符串左边,添加 (4-text.length=3) 个字符 22 至原来的字符串
print(text.padLeft(4, '22')); // 返回 2222225
// 04 当时间的分钟数是个位数时,可以通过左边补 0 达到双位数显示的效果
print(text.padLeft(2, "0")); // 返回 05
// 05 如果 width 小于字符串的长度,则返回原字符串
print(text.padLeft(1, '2')); // 返回 5

padRight

源码如下所示

String padRight(int width, [String padding = ' ']);

语法

字符串右补齐,指定 width 后,如果有剩余位则使用指定字符替换。如果指定 width 小于字符串长度,则返回原字符串。

第一个参数 width 不是补齐后的字符串总长度,你可以用 width 减去原来字符串的长度,得到的结果表示将会在字符串右边添加多少个补齐的字符(见下面的 01、02、03 例子)

第二个参数 padding 为可选参数,表示要补齐的字符,不指定时默认补上空格。

举例

String text = "5";
// 01 在指定字符串右边,添加 (4-text.length=3) 个空格至原来的字符串
print(text.padRight(4)); // 返回 "5   ",注意,字符 5 右边有三个空格
// 02 在指定字符串右边,添加 (4-text.length=3) 个字符 2 至原来的字符串
print(text.padRight(4, '2')); // 返回 5222
// 03 在指定字符串右边,添加 (4-text.length=3) 个字符 22 至原来的字符串
print(text.padRight(4, '22')); // 返回 5222222
// 04 如果 width 小于字符串的长度,则返回原字符串
print(text.padRight(1, '2')); // 返回 5

七:字符串去除空格

trim

源码如下所示

String trim();

语法

去除字符串中左右两边的空格,注意不是去掉字符串中所有的空格。如果两边没有空格,则返回原字符串。

举例

String text = "   a b c "; // 长度为 9 的字符串
print(text.trim()); // 返回长度为 5 的字符串 "a b c"

trimLeft

源码如下所示

String trimLeft();

语法

去除字符串中左边的空格,如果左边没有空格,则返回原字符串。

举例

String text = "   a b c "; // 长度为 9 的字符串
print(text.trimLeft()); // 返回长度为 6 的字符串 "a b c ",字符 c 右边的空格被保留

trimRight

源码如下所示

String trimRight();

语法

去除字符串中右边的空格,如果右边没有空格,则返回原字符串。

举例

String text = "   a b c "; // 长度为 9 的字符串
print(text.trimRight()); // 返回长度为 8 的字符串 "   a b c",字符 a 左边的三个空格被保留

八:字符串替换

replaceAll

源码如下所示

String replaceAll(Pattern from, String replace);

语法

替换掉字符串中全部符合条件的字符。如果没有符合条件的,则返回原字符串。

第一个参数 from 表示字符串中被替换掉的字符,第二个参数 replace 表示替换为什么字符。

举例

String text = "abcdabcd";
print(text.replaceAll("ab", "xy")); // 返回 xycdxycd

replaceFirst

源码如下所示

String replaceFirst(Pattern from, String to, [int startIndex = 0]);

语法

只替换掉第一个符合条件的字符。

第一个参数 from 表示字符串中被替换掉的字符,第二个参数 to 表示替换为什么字符,第三个参数为可选参数,表示从哪个索引位置开始替换,默认为 0 。

举例

String text = "abcdabcd";
// 01 只替换掉第一个符合条件的字符
print(text.replaceFirst("ab", "xy")); // 返回 xycdabcd
// 02 从索引 1 位置后面开始,替换掉第一个符合条件的字符
print(text.replaceFirst("ab", "xy", 1)); // 返回 abcdxycd

replaceRange

源码如下所示

String replaceRange(int start, int? end, String replacement);

语法

替换掉指定范围内的字符。有效取值范围是 0 <= start <= end <= 字符串.length

第一个参数 start 表示从哪个索引位置开始替换,包括该索引。

第二个参数 end 表示从哪个索引位置结束替换,不包括该索引。因为 end 为可空参数,当 end 为 null 时,表示到字符串末尾。

第三个参数 replacement 表示替换为什么字符。

举例

String text = "abcdabcd";
// 01 从索引 0 位置开始,到索引 3 位置结束(但不包括该索引),中间的字符被替换为 m
print(text.replaceRange(0, 3, "m")); // 返回 mdabcd
// 02 从索引 0 位置开始到末尾,中间的字符被替换为 m
print(text.replaceRange(0, null, "m")); // 返回 m

replaceAllMapped

源码如下所示

String replaceAllMapped(Pattern from, String Function(Match match) replace);

语法

替换掉所有符合条件的字符。用方法的返回值替换指定的字符,如果没有匹配的字符,则返回原字符串。

第一个参数 from 表示字符串中被替换掉的字符,

第二个参数 replace 表示如果有匹配的字符,则用指定的字符作为返回值替,换掉字符串中符合条件的字符。最终的效果其实和方法 replaceAll 是一样的。

举例

String text = "abcdabcd";
// 用 xy 替换掉字符串中的 ab
String str = text.replaceAllMapped("ab", (Match match) => "xy");
print(str); // 返回 xycdxycd

replaceFirstMapped

源码如下所示

String replaceFirstMapped(Pattern from, String replace(Match match), [int startIndex = 0]);

语法

只替换掉第一个符合条件的字符。用方法的返回值替换指定的字符,如果没有匹配的字符,则返回原字符串。

第一个参数 from 表示字符串中被替换掉的字符,

第二个参数 replace 表示如果有匹配的字符,则用指定的字符作为返回值,替换掉字符串中第一个符合条件的字符。最终的效果其实和方法 replaceFirst 是一样的。

第三个参数 startIndex 为可选参数,表示从哪个索引位置开始替换,默认为 0,不能大于字符串的长度。

举例

String text = "abcdabcd";
// 01 用 xy 替换掉字符串中第一个符合条件的 ab
String str1 = text.replaceFirstMapped("ab", (Match match) => "xy");
print(str1); // 返回 xycdabcd
// 02 从索引 1 位置处开始,用 xy 替换掉字符串中第一个符合条件的 ab
String str2 = text.replaceFirstMapped("ab", (Match match) => "xy", 1);
print(str2); // 返回 abcdxycd

九:字符串先后比较

compareTo

源码如下所示

int compareTo(String other);

语法

比较字符在 ASCII 码的位置。

如果当前字符在被比较字符后面,返回 1,位置相等返回 0,如果当前字符在被比较字符前面,返回 -1。

在 ASCII 码中,48~57 为 0到9十个阿拉伯数字,65~90 为 26 个大写英文字母,97~122 为 26 个小写英文字母。

举例

String text = "b";
print(text.compareTo('a')); // b>a,返回 1
print(text.compareTo('b')); // b=b,返回 0
print(text.compareTo('c')); // b<c,返回 -1
print(text.compareTo('7')); // 字母在数字后面,返回 1
print(text.compareTo('B')); // 小写字母在大写字母后面,返回 1

十:获取字符串的 Unicode 编码

codeUnitAt

源码如下所示

int codeUnitAt(int index);

语法

返回指定索引处字符的 Unicode 十进制编码

举例

String text = "Allen Su";
print(text.codeUnitAt(0)); // 索引 0 处的字符是 A,A 的 Unicode 十进制编码是 108
print(text.codeUnitAt(5)); // 索引 5 处的字符是空格,空格的 Unicode 十进制编码是 32

还有两个方法 matchAsPrefix 和 allMatches ,实在是过于冷门,这里就不再进行说明了。

如果你需要了解 Dart 中 String 字符串类型的属性,可以点击链接跳转。

这篇博客写完实属不易,好在坚持给一口气写完了。

你的问题得到解决了吗?欢迎在评论区留言。

赠人玫瑰,手有余香,如果觉得文章不错,希望可以给个一键三连,感谢。


结束语

技术是一点一点积累的,大神也不是一天就可以达到的。原地不动就是退步,所以每天进步一点点。

最后,附上一句格言:”好学若饥,谦卑若愚”,望共勉。