从源码详细学习Dart字符串,基本使用在上篇已经介绍过了,就不赘述了。
首先找到string.dart 文件属于 dart.core
模块
字符串由Unicode UTF-16代码单元序列表示,可通过[codeUnitAt]或[codeUnits]成员访问:
var string = 'Dart';
string.codeUnitAt(0); // 68
string.codeUnits; // [68, 97, 114, 116]
序列可以通过index 获取每个字符:
var string = 'Dart';
print(string[0]); // D
substring截取:
var string = 'Dart is fun';
var newString = string.substring(0, 5);
runes 是可以描述字符的32位对象,下面例子可以看出runes使用和codeUnits区别:
var runesStr = 'dart';
print(runesStr.runes.toList());
var string = '𝄞';
print(string.runes);
print(string.codeUnits);
runes是32位,codeUnits 是16位。
abstract class String implements Comparable<String>, Pattern
接口名称 | 用途 |
---|---|
Comparable | 对比接口 |
Pattern | 搜索匹配接口 |
String 基于Comparable、Pattern具备其功能
charCodes 16位以内:
/// Allocates a new string containing the specified [charCode].
///
/// If the [charCode] can be represented by a single UTF-16 code unit, the new
/// string contains a single code unit. Otherwise, the [length] is 2 and
/// the code units form a surrogate pair. See documentation for
/// [fromCharCodes].
///
/// Creating a [String] with one half of a surrogate pair is allowed.
external factory String.fromCharCode(int charCode);
使用:
main() {
print(String.fromCharCode(97)); // a
}
charCodes 超过16位
源码函数:
/// If [start] and [end] are provided, only the values of [charCodes]
/// at positions from `start` to, but not including, `end`, are used.
/// The `start` and `end` values must satisfy
/// `0 <= start <= end <= charCodes.length`.
external factory String.fromCharCodes(Iterable<int> charCodes,
[int start = 0, int? end]);
var clef = String.fromCharCodes([0x1D11E]);
clef.codeUnitAt(0); // 0xD834
clef.codeUnitAt(1); // 0xDD1E
作用: flutter 启动的时候可以设置环境变量,可以通过fromEnvironment获取环境变量的内容。
API源码:
external const factory String.fromEnvironment(String name,
{String defaultValue = ""});
例子:
const String.fromEnvironment("defaultFloo", defaultValue: "no floo")
可以通过bool.hasEnvironment
判断是否存在
const maybeDeclared = bool.hasEnvironment("maybeDeclared")
? String.fromEnvironment("maybeDeclared")
: null;
API:
int get length;
例子:
'Dart'.length; // 4
'Dart'.runes.length; // 4
var clef = '\u{1D11E}';
clef.length; // 2
clef.runes.length; // 1
检查每个code units 是否相等,不比较Unicode的等价性。
API源码:
bool operator ==(Object other);
作用: 比较字符串是否相,返回整型,0相等,-1不相等。
API源码:
int compareTo(String other);
例子:
var a = 'a';
var b = 'a';
var c = 'c';
print(a.compareTo(b)); //0
print(a.compareTo(c)); //-1
作用: 判断是否以XX字符串结尾
API源码:
bool endsWith(String other);
例子:
'Dart'.endsWith('t'); // true
作用: 判断字符串是否已XX开头
API源码:
bool startsWith(Pattern pattern, [int index = 0]);
参数一: Pattern
是String,RegExp 都去实现的抽象类。
参数二: 右偏移个数
例子:
var start = '我爱你中国';
print(start.startsWith('你', 2)); //true
也可以跟正则:
print('dart'.startsWith(RegExp(r'art'), 1)); //true
作用: 匹配查找字符串的位置,返回int 位置
API源码:
/// Returns the position of the first match of [pattern] in this string,
/// starting at [start], inclusive:
/// ```dart
/// var string = 'Dartisans';
/// string.indexOf('art'); // 1
/// string.indexOf(RegExp(r'[A-Z][a-z]')); // 0
/// ```
/// Returns -1 if no match is found:
/// ```dart
/// string.indexOf(RegExp(r'dart')); // -1
/// ```
/// The [start] must be non-negative and not greater than [length].
int indexOf(Pattern pattern, [int start = 0]);
搜索字符在字符串的位置, 参数类似 startsWith。
例子:
print('dart'.indexOf('art')); //1
print('dart'.indexOf('t')); //3
print('dart'.indexOf('b')); //-1
print('dart'.indexOf(RegExp(r'dart'))); //0
print('dart'.indexOf('d')); //0
print('dart'.indexOf('d', 1)); //-1
print('aabbbcc'.indexOf('b')); //2
print('aabbbcc'.indexOf('b', 3)); //3
作用: 匹配查找字符串的最后一个的位置,返回int 位置
API源码:
/// The starting position of the last match [pattern] in this string.
///
/// Finds a match of pattern by searching backward starting at [start]:
/// ```dart
/// var string = 'Dartisans';
/// string.lastIndexOf('a'); // 6
/// string.lastIndexOf(RegExp(r'a(r|n)')); // 6
/// ```
/// Returns -1 if [pattern] could not be found in this string.
/// ```dart
/// string.lastIndexOf(RegExp(r'DART')); // -1
/// ```
/// If [start] is omitted, search starts from the end of the string.
/// If supplied, [start] must be non-negative and not greater than [length].
int lastIndexOf(Pattern pattern, [int? start]);
同理 indexOf 只是会选择最后一个匹配的位置
作用: 判断字符串是否是空
API源码:
/// Whether this string is empty.
bool get isEmpty;
/// Whether this string is not empty.
bool get isNotEmpty;
因为空安全所以不存在null去判断这种情况。
例子:
String a = '';
print(a.isEmpty);
print(a.isNotEmpty);
作用: 字符串截取子字符串
API源码:
/// The substring of this string from [start],inclusive, to [end], exclusive.
///
/// Example:
/// ```dart
/// var string = 'dartlang';
/// string.substring(1); // 'artlang'
/// string.substring(1, 4); // 'art'
/// ```
String substring(int start, [int? end]);
例子:
var str = '我爱你中国';
var subStr1 = str.substring(1);
print(subStr1);
var subStr2 = str.substring(1, 3);
print(subStr2);
打印结果:
爱你中国
爱你
作用: 去除字符串空白格
'\tDart is fun\n'.trim(); // 'Dart is fun'
例子:
去除空白格返回的字符串还是之前的地址:
var str1 = 'Dart';
var str2 = str1.trim();
identical(str1, str2); // true
去除空白格的uniCode 值如下:
/// 0009..000D ; White_Space # Cc <control-0009>..<control-000D>
/// 0020 ; White_Space # Zs SPACE
/// 0085 ; White_Space # Cc <control-0085>
/// 00A0 ; White_Space # Zs NO-BREAK SPACE
/// 1680 ; White_Space # Zs OGHAM SPACE MARK
/// 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE
/// 2028 ; White_Space # Zl LINE SEPARATOR
/// 2029 ; White_Space # Zp PARAGRAPH SEPARATOR
/// 202F ; White_Space # Zs NARROW NO-BREAK SPACE
/// 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE
/// 3000 ; White_Space # Zs IDEOGRAPHIC SPACE
///
/// FEFF ; BOM ZERO WIDTH NO_BREAK SPACE
trimLeft
和 trimRight
分别去除左边和右边。
作用: 就是字符串重复repeat
字符串 = 字符串 * 个数
API源码:
String operator *(int times);
例子:
var times = '哈';
var timesRepeat = times * 10;
print(timesRepeat); //哈哈哈哈哈哈哈哈哈哈
作用: 字符串补齐
API源码:
String padLeft(int width, [String padding = ' ']);
String padRight(int width, [String padding = ' ']);
例子:
多用于字符串补0处理,举例padleft,padRight同理。
var list = [];
for (var i = 0; i < 100; i++) {
list.add(i.toString().padLeft(4, '0'));
}
print(list); //[0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 0008, 0009, 0010, 0011, 0012, 0013, 0014, 0015,...]
作用: 判断字符串是否包含子字符串或者正则
APi源码:
/// Example:
/// ```dart
/// var string = 'Dart strings';
/// string.contains('D'); // true
/// string.contains(RegExp(r'[A-Z]')); // true
/// ```
/// If [startIndex] is provided, this method matches only at or after that
/// index:
/// ```dart
/// string.contains('D', 1); // false
/// string.contains(RegExp(r'[A-Z]'), 1); // false
/// ```
/// The [startIndex] must not be negative or greater than [length].
bool contains(Pattern other, [int startIndex = 0]);
例子:
print('Dart'.contains('D')); // true
print('Dart'.contains('D', 1)); // false
作用: 替换掉第一个符合条件的字符
参数:
API源码:
String replaceFirst(Pattern from, String to, [int startIndex = 0]);
例子:
var replaceFristResult = 'DartD'.replaceFirst('D', 'X');
print(replaceFristResult);
var replaceFristResult1 = 'DartD'.replaceFirst('D', 'X', 1);
print(replaceFristResult1);
var replaceFristResult2 = 'DartD'.replaceFirst(r'D', 'X', 1);
print(replaceFristResult2);
作用: 相比replaceFirst,替换字符可以根据匹配match结果去替换,更加灵活。
API源码:
/// Replace the first occurrence of [from] in this string.
///
/// Returns a new string, which is this string
/// except that the first match of [from], starting from [startIndex],
/// is replaced by the result of calling [replace] with the match object.
///
/// The [startIndex] must be non-negative and no greater than [length].
String replaceFirstMapped(Pattern from, String replace(Match match),
[int startIndex = 0]);
例子:
String replace(Match match) {
print(match.start);
print(match.end);
print(match.groupCount);
print(match.input);
print(match.pattern);
return 'X';
}
var replaceFristResult = 'DartD'.replaceFirstMapped('D', replace, 1);
print(replaceFristResult);
作用: 类似replaceFirst ,replaceAllMapped只是全部进行替换。
API源码:
/// Replaces all substrings that match [from] with [replace].
///
/// Creates a new string in which the non-overlapping substrings matching
/// [from] (the ones iterated by `from.allMatches(thisString)`) are replaced
/// by the literal string [replace].
/// ```dart
/// 'resume'.replaceAll(RegExp(r'e'), 'é'); // 'résumé'
/// ```
/// Notice that the [replace] string is not interpreted. If the replacement
/// depends on the match (for example on a [RegExp]'s capture groups), use
/// the [replaceAllMapped] method instead.
String replaceAll(Pattern from, String replace);
/// Replace all substrings that match [from] by a computed string.
///
/// Creates a new string in which the non-overlapping substrings that match
/// [from] (the ones iterated by `from.allMatches(thisString)`) are replaced
/// by the result of calling [replace] on the corresponding [Match] object.
///
/// This can be used to replace matches with new content that depends on the
/// match, unlike [replaceAll] where the replacement string is always the same.
///
/// The [replace] function is called with the [Match] generated
/// by the pattern, and its result is used as replacement.
///
/// The function defined below converts each word in a string to simplified
/// 'pig latin' using [replaceAllMapped]:
/// ```dart
/// pigLatin(String words) => words.replaceAllMapped(
/// RegExp(r'\b(\w*?)([aeiou]\w*)', caseSensitive: false),
/// (Match m) => "${m[2]}${m[1]}${m[1]!.isEmpty ? 'way' : 'ay'}");
///
/// pigLatin('I have a secret now!'); // 'Iway avehay away ecretsay ownay!'
/// ```
String replaceAllMapped(Pattern from, String Function(Match match) replace);
作用: 替换固定范围的内容
API源码:
/// Replaces the substring from [start] to [end] with [replacement].
///
/// Creates a new string equivalent to:
/// ```dart
/// this.substring(0, start) + replacement + this.substring(end)
/// ```
/// The [start] and [end] indices must specify a valid range of this string.
/// That is `0 <= start <= end <= this.length`.
/// If [end] is `null`, it defaults to [length].
String replaceRange(int start, int? end, String replacement);
例子:
var str = 'hello world';
print(str.replaceRange(6, 11, 'dart')); //hello dart
作用: 字符串分割成数组
API源码:
/// Splits the string at matches of [pattern] and returns a list of substrings.
///
/// Finds all the matches of `pattern` in this string,
/// as by using [Pattern.allMatches],
/// and returns the list of the substrings between the matches,
/// before the first match, and after the last match.
/// ```dart
/// var string = "Hello world!";
/// string.split(" "); // ["Hello", "world!"];
/// ```
/// If the pattern doesn't match this string at all,
/// the result is always a list containing only the original string.
///
/// If the [pattern] is a [String], then it's always the case that:
/// ```dart
/// string.split(pattern).join(pattern) == string
/// ```
///
/// If the first match is an empty match at the start of the string,
/// the empty substring before it is not included in the result.
/// If the last match is an empty match at the end of the string,
/// the empty substring after it is not included in the result.
/// If a match is empty, and it immediately follows a previous
/// match (it starts at the position where the previous match ended),
/// then the empty substring between the two matches is not
/// included in the result.
/// ```dart
/// var string = "abba";
/// var re = RegExp(r"b*");
/// // re.allMatches(string) will find four matches:
/// // * empty match before first "a".
/// // * match of "bb"
/// // * empty match after "bb", before second "a"
/// // * empty match after second "a".
/// print(string.split(re)); // ["a", "a"]
/// ```
///
/// A non-empty match at the start or end of the string, or after another
/// match, is not treated specially, and will introduce empty substrings
/// in the result:
/// ```dart
/// var string = "abbaa";
/// string.split("a"); // ["", "bb", "", ""]
/// ```
///
/// If this string is the empty string, the result is an empty list
/// if `pattern` matches the empty string, since the empty string
/// before and after the first-and-last empty match are not included.
/// (It is still a list containing the original empty string `[""]`
/// if the pattern doesn't match).
/// ```dart
/// var string = "";
/// string.split(""); // []
/// string.split("a"); // [""]
/// ```
///
/// Splitting with an empty pattern splits the string into single-code unit
/// strings.
/// ```dart
/// var string = "Pub";
/// string.split(""); // ["P", "u", "b"]
/// // Same as:
/// [for (var unit in string.codeUnits)
/// String.fromCharCode(unit)] // ["P", "u", "b"]
/// ```
///
/// Splitting happens at UTF-16 code unit boundaries,
/// and not at rune (Unicode code point) boundaries:
/// ```dart
/// // String made up of two code units, but one rune.
/// string = '\u{1D11E}';
/// string.split('') // ["\ud834", "\udd1e"] - 2 unpaired surrogate values
/// ```
/// To get a list of strings containing the individual runes of a string,
/// you should not use split.
/// You can instead get a string for each rune as follows:
/// ```dart
/// [for (var run in string.runes) String.fromCharCode(rune)]
/// ```
List<String> split(Pattern pattern);
例子:
参考官方API ,全面专业。
var string = "Hello world!";
string.split(" "); //["Hello", "world!"];
string.split(pattern).join(pattern) == string
var string = "abba";
var re = RegExp(r"b*");
// re.allMatches(string) will find four matches:
// * empty match before first "a".
// * match of "bb"
// * empty match after "bb", before second "a"
// * empty match after second "a".
print(string.split(re)); // ["a", "a"]
var string = "abbaa";
string.split("a"); // ["", "bb", "", ""]
var string = "";
string.split(""); // []
string.split("a"); // [""]
var string = "Pub";
string.split(""); // ["P", "u", "b"]
// Same as:
[for (var unit in string.codeUnits)
String.fromCharCode(unit)] // ["P", "u", "b"]
// String made up of two code units, but one rune.
string = '\u{1D11E}';
string.split('') // ["\ud834", "\udd1e"] - 2 unpaired surrogate values
作用: 替换字符串,将匹配和非匹配的分离开来分别处理
API源码:
/// Splits the string, converts its parts, and combines them into a new
/// string.
///
/// The [pattern] is used to split the string
/// into parts and separating matches.
/// Each match of [Pattern.allMatches] of [pattern] on this string is
/// used as a match, and the substrings between the end of one match
/// (or the start of the string) and the start of the next match (or the
/// end of the string) is treated as a non-matched part.
/// (There is no omission of leading or trailing empty matchs, like
/// in [split], all matches and parts between the are included.)
///
/// Each match is converted to a string by calling [onMatch]. If [onMatch]
/// is omitted, the matched substring is used.
///
/// Each non-matched part is converted to a string by a call to [onNonMatch].
/// If [onNonMatch] is omitted, the non-matching substring itself is used.
///
/// Then all the converted parts are concatenated into the resulting string.
/// ```dart
/// 'Eats shoots leaves'.splitMapJoin((RegExp(r'shoots')),
/// onMatch: (m) => '${m[0]}', // (or no onMatch at all)
/// onNonMatch: (n) => '*'); // Result: "*shoots*"
/// ```
String splitMapJoin(Pattern pattern,
{String Function(Match)? onMatch, String Function(String)? onNonMatch});
参数:
例子:
String onMatch(Match m) {
return 'dd';
}
String onNonMatch(n) {
return '*';
}
var s = 'aabbcc'.splitMapJoin((RegExp(r'bb')),
onMatch: onMatch, // (or no onMatch at all)
onNonMatch: onNonMatch); // Result: "*shoots*"
print(s); //*dd*