ZetCode

Dart string

last modified October 18, 2026

Dart string tutorial shows how to work with strings in Dart language.

Dart string

A string is a sequence of UTF-16 code units. It is used to represent some text in a program. A character may be represented by multiple code points. Each code point can have one or two code units.

Strings are immutable in Dart. There are methods such as toLowerCase or split that return a modified string, but the original string is intact.

A rune is an integer representing a Unicode code point. The runes property of a string returns its runes.

A string in Dart is an object of the String class. There are several methods that we can call on a string object.

Dart simple string

The following is a simple Dart program with strings.

main.dart
void main() {
  final text = 'There are six falcons';
  print(text);

  final len = text.length;
  print('The string has ' + len.toString() + ' characters');

  final word = 'falcon ';
  print(word * 3);
}

String literals are delimited with single or double quotes.

final len = text.length;

The length property returns the length of the string, i.e. the number of UTF-16 code units in the string.

print('The string has ' + len.toString() + ' characters');

Strings can be concatenated with the + operator. The number must be converted to a string first; the interpolation shown later is usually nicer.

final word = 'falcon ';
print(word * 3);

The * operator repeats a string.

$ dart main.dart
There are six falcons
The string has 21 characters
falcon falcon falcon 

Dart string delimiters

Strings are delimited either with single or double quotes. The quotes can be nested to create quotations or direct speech if needed. Otherwise, the inner quote must be escaped with a backslash.

main.dart
void main() {
  final text1 = "old falcon";
  final text2 = 'new book';
  final text3 = "This was a 'great movie'";
  final text4 = 'He said: "I saw an old man in the park."';
  final text5 = 'It\'s a nice day';

  print(text1);
  print(text2);
  print(text3);
  print(text4);
  print(text5);
}

The example presents string delimiters in Dart. Adjacent string literals are joined by the compiler, which is handy for splitting a long text into several lines of source code: 'one ' 'two ' 'three' is the same as 'one two three'.

$ dart main.dart
old falcon
new book
This was a 'great movie'
He said: "I saw an old man in the park."
It's a nice day

Dart string length

The length property returns the length of a string in UTF-16 code units.

main.dart
void main() {
  final word = 'čerešňa';
  print(word.length);
  print(word.codeUnits);
  print(word.runes);

  final word2 = '合気道';
  print(word2.length);
  print(word2.codeUnits);
  print(word2.runes);

  final emoji = '🐘';
  print(emoji.length);
  print(emoji.runes.length);
}

In the example, we have strings with non-ASCII characters. The codeUnits property returns an unmodifiable list of the UTF-16 code units of the string. The runes property returns an iterable of Unicode code points. For most characters, there is one code unit per code point. Characters outside the Basic Multilingual Plane, such as the elephant emoji, take two code units, so length returns 2 for a single visible symbol.

$ dart main.dart
7
[269, 101, 114, 101, 353, 328, 97]
(269, 101, 114, 101, 353, 328, 97)
3
[21512, 27671, 36947]
(21512, 27671, 36947)
2
1

Dart multiline string

Multiline strings are created with triple single or double quotes.

main.dart
void main() {
  final sonnet55 = '''
Not marble nor the gilded monuments
Of princes shall outlive this powerful rhyme,
But you shall shine more bright in these contents
Than unswept stone besmeared with sluttish time.
When wasteful war shall statues overturn,
And broils root out the work of masonry,
Nor Mars his sword nor war's quick fire shall burn
The living record of your memory.
'Gainst death and all-oblivious enmity
Shall you pace forth; your praise shall still find room
Even in the eyes of all posterity
That wear this world out to the ending doom.
So, till the Judgement that yourself arise,
You live in this, and dwell in lovers' eyes.''';

  print(sonnet55);
}

The example prints a verse created with triple single quotes. A newline directly after the opening quotes is ignored, which lets us start the text on its own line.

$ dart main.dart
Not marble nor the gilded monuments
Of princes shall outlive this powerful rhyme,
But you shall shine more bright in these contents
Than unswept stone besmeared with sluttish time.
When wasteful war shall statues overturn,
And broils root out the work of masonry,
Nor Mars his sword nor war's quick fire shall burn
The living record of your memory.
'Gainst death and all-oblivious enmity
Shall you pace forth; your praise shall still find room
Even in the eyes of all posterity
That wear this world out to the ending doom.
So, till the Judgement that yourself arise,
You live in this, and dwell in lovers' eyes.

Dart string is immutable

A string cannot be modified. We can call methods that return a modified string.

main.dart
void main() {
  final text = 'a red fox';
  final parts = text.split(' ');

  print(parts);
  print(text);
  print(text.toUpperCase());
  print(text);
}

With the split method, we split the string at matches of the pattern and return a list of substrings. The toUpperCase method returns a new string. The original string is preserved.

$ dart main.dart
[a, red, fox]
a red fox
A RED FOX
a red fox

Dart string escape sequences

Escape sequences are special characters that have a specific meaning when used within a string literal. For instance, the new-line \n escape sequence causes the next character to appear on a new line.

main.dart
void main() {
  final text1 = 'a red \n fox';
  final text2 = 'a red \t fox';
  final text3 = 'a red \u0041 \u{1F98A} fox';
  final text4 = 'a red \x41 fox';

  print(text1);
  print(text2);
  print(text3);
  print(text4);
}

In the example, we use several escape sequences. The \n adds a newline, the \t inserts a tab. The \u0041 and \x41 forms insert a character by its code (here the letter A), and \u{1F98A} is the form for code points with more than four hex digits (a fox emoji). Other escapes are \\ for a backslash, \$ for a dollar sign, \r for a carriage return, and \b for the backspace control character, which most terminals interpret as a cursor move.

$ dart main.dart
a red 
 fox
a red 	 fox
a red A 🦊 fox
a red A fox

Dart raw string

In raw strings, the escape characters are not interpreted. A raw string is created by prepending a string literal with the r character. Raw strings are useful for regular expressions and Windows paths.

main.dart
void main() {
  print(r'falcon\tfalcon\tfalcon');
  print('becomes');
  print('falcon\tfalcon\tfalcon');
}

The example uses a raw string.

$ dart main.dart
falcon\tfalcon\tfalcon
becomes
falcon	falcon	falcon

Dart string interpolation

String interpolation is the process of evaluating a string containing variables and expressions. When an interpolated string is evaluated the variables and expressions are replaced with their corresponding values.

In Dart, the $ is used to interpolate variables and ${} expressions.

main.dart
void main() {
  final name = 'John Doe';
  final occupation = 'gardener';
  print('$name is a $occupation');

  final x = 12;
  final y = 14;
  print('$x * $y = ${x * y}');

  final words = ['falcon', 'owl'];
  print('Count: ${words.length}, first: ${words.first.toUpperCase()}');
}

In the example, we interpolate variables and expressions.

print('$name is a $occupation');

Variables are interpolated by prepending their names with the dollar sign.

print('$x * $y = ${x * y}');

If we need to evaluate more complex expressions, such as an arithmetic operation or a property access, we use ${}. The braces can be omitted only for simple identifiers.

$ dart main.dart
John Doe is a gardener
12 * 14 = 168
Count: 2, first: FALCON

If we need to output a dollar sign, we escape it: \$.

main.dart
void main() {
  final item = 'beer';
  final price = 4.5;

  print('The price of a $item is \$$price');
}

The example prints the price of a beer in dollars.

$ dart main.dart
The price of a beer is $4.5

Dart string isEmpty/isNotEmpty

With isEmpty and isNotEmpty we can check if a string in Dart is empty or not empty, respectively.

main.dart
void main() {
  final word1 = '';
  final word2 = 'falcon';

  if (word1.isEmpty) {
    print('word1 is empty');
  } else {
    print('word1 is not empty');
  }

  if (word2.isNotEmpty) {
    print('word2 is not empty');
  } else {
    print('word2 is empty');
  }
}

The example calls the properties on two words. They are preferable to comparing the length with zero.

$ dart main.dart
word1 is empty
word2 is not empty

Dart trim string

We can remove whitespace from the string with trim, trimLeft, and trimRight methods.

main.dart
void main() {
  final word = '  falcon\t';

  print('|$word|');
  print('|${word.trim()}|');
  print('|${word.trimLeft()}|');
  print('|${word.trimRight()}|');
  print('|$word|');
}

The example uses the methods on a string which has leading and trailing whitespace characters. The tab at the end of the original string is rendered as spaces by the terminal.

$ dart main.dart
|  falcon	|
|falcon|
|falcon	|
|  falcon|
|  falcon	|

Dart string search

The contains, startsWith, endsWith, indexOf, and lastIndexOf methods search in a string. The index methods return -1 when there is no match.

main.dart
void main() {
  const text = 'The old falcon watches the old river';

  print(text.contains('falcon'));
  print(text.startsWith('The'));
  print(text.endsWith('river'));
  print(text.indexOf('old'));
  print(text.lastIndexOf('old'));
  print(text.indexOf('old', 5));
  print(text.indexOf('snow'));
}

The optional second argument of indexOf is the position where the search starts; thus, the third call finds the second occurrence of "old".

$ dart main.dart
true
true
true
4
27
27
-1

Dart substring and replace

The substring method returns a part of a string. The replaceAll and replaceFirst methods replace occurrences of a pattern with another string.

main.dart
void main() {
  const text = 'The old falcon';

  print(text.substring(4));
  print(text.substring(4, 7));
  print(text.replaceAll('old', 'young'));
  print(text.replaceFirst('o', '0'));
  print(text.replaceAll(RegExp(r'[aeiou]'), '*'));
}

The end index of substring is exclusive. Invalid indexes throw a RangeError. The patterns can be regular expressions.

$ dart main.dart
old falcon
old
The young falcon
The 0ld falcon
Th* *ld f*lc*n

Dart string case and padding

The toUpperCase and toLowerCase methods change the case. The padLeft and padRight methods pad a string to a minimum width, which is useful for aligning columns.

main.dart
void main() {
  const name = 'falcon';

  print(name.toUpperCase());
  print('FALCON'.toLowerCase());
  print('|${name.padLeft(10)}|');
  print('|${name.padRight(10, '.')}|');
  print('7'.padLeft(3, '0'));

  final items = {'apple': 3, 'banana': 12, 'kiwi': 7};
  items.forEach((k, v) => print('${k.padRight(8)}${v.toString().padLeft(3)}'));
}

Without the second argument, the padding character is a space.

$ dart main.dart
FALCON
falcon
|    falcon|
|falcon....|
007
apple     3
banana   12
kiwi      7

Dart string comparison

Strings are compared for equality with the == operator, which compares the content. The compareTo method returns a negative number, zero, or a positive number and is used for ordering. The comparison is based on UTF-16 code units, so it is case-sensitive.

main.dart
void main() {
  print('falcon' == 'falcon');
  print('falcon' == 'Falcon');
  print('falcon'.toLowerCase() == 'Falcon'.toLowerCase());

  print('apple'.compareTo('banana'));
  print('banana'.compareTo('apple'));
  print('apple'.compareTo('apple'));
  print('Zebra'.compareTo('apple'));
}

The upper-case letter Z has a smaller code than the lower-case a; therefore, "Zebra" is ordered before "apple".

$ dart main.dart
true
false
true
-1
1
0
-1

Dart string join

The join method of an iterable concatenates its elements with a separator.

main.dart
void main() {
  final words = ['sky', 'cloud', 'rain'];

  print(words.join());
  print(words.join(', '));
  print(words.map((w) => w.toUpperCase()).join('-'));
}

Without an argument, join uses an empty separator.

$ dart main.dart
skycloudrain
sky, cloud, rain
SKY-CLOUD-RAIN

Dart string iterate

We can iterate over the elements of a string with the help of the runes property and the String.fromCharCode method. Indexing a string with [] returns a code unit as a one-character string.

main.dart
void main() {
  const word = 'falcon';

  for (final c in word.runes) {
    print(String.fromCharCode(c));
  }

  print(word[0]);
  print(word.codeUnitAt(0));
  print(word.split('').reversed.join());
}

The example prints the characters of the 'falcon' word to the terminal; each on a separate line. Then it shows the first character, its code, and the reversed word. Note that reversing with split('') breaks characters outside the Basic Multilingual Plane; the characters package handles such cases.

$ dart main.dart
f
a
l
c
o
n
f
102
noclaf

Dart nullable strings

With null safety, a String cannot be null. A variable that may have no value is declared as String?. The null-aware operators make working with such values concise.

main.dart
void main() {
  String? name;

  print(name?.length);
  print(name ?? 'anonymous');

  name = 'Jane';
  print(name.length);
  print(name?.toUpperCase());
}

The ?. operator short-circuits to null and ?? provides a default. After the assignment, the compiler knows that name is not null, so length can be accessed directly (type promotion).

$ dart main.dart
null
anonymous
4
JANE

Source

Dart String - API reference

In this article we have covered strings in Dart.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Dart tutorials.