Strings in Dart

By Syncfusion®, Inc. · Last updated

How to create strings, put values inside them, compare, search, cut, change, split and join them, build long text with StringBuffer, and handle Unicode and emoji.

What Is a String?

String = a piece of text: letters, digits, spaces, symbols and emoji, in order.

For example:

  • a name: 'Asha'
  • a sentence: 'Today is Sports Day.'
  • digits you never do maths on: '600001'

Each character has a position, starting at 0, just like a list (see Lists).

Simple lesson: a String is text, and Dart gives you many tools to search, cut and change it.

A Real-World Example

The school app shows "Welcome, ASHA!" on the home screen.

  • The name comes from the database as ' asha ', with extra spaces.
  • The app trims the spaces, makes it upper case, and puts it inside a sentence.

Three string tools, one line of code. Try the tools yourself:

Every Run box on this page runs on the course's Dart runner in your browser.

Strings never change in place. Every method gives you a new string.

What You Will Learn

In this lesson, you will learn:

  1. How to create strings, including multi-line and raw strings.
  2. String properties, interpolation, joining and comparing.
  3. How to search, extract and change parts of a string.
  4. How to change case, trim, split and join.
  5. How to build long text with StringBuffer, and handle Unicode and emoji.

String Fundamentals

Creating Strings

Four ways to write a string

Single, double, multi-line and raw

void main() {
  var school = 'Green Valley';
  var quote = "It's Sports Day!";
  var address = '''Green Valley School
12, MG Road
Pune''';
  var path = r'C:\notes\new $file';
  print(school);
  print(quote);
  print(address);
  print(path);
}

Escape sequence = a backslash code for a special character, like \n (new line), \t (tab), \' (a quote) or \$ (a dollar sign).

Simple lesson: use single quotes normally, three quotes for many lines, and r'' to keep backslashes.

String Properties

PropertyGives'Asha' gives
lengthnumber of UTF-16 units4
isEmptytrue if it is ''false
isNotEmptytrue if it has texttrue
codeUnitsthe number code of each unit[65, 115, 104, 97]
runesthe Unicode code of each character(65, 115, 104, 97)

String properties

void main() {
  var name = 'Asha';
  print(name.length);
  print(name.isEmpty);
  print(''.isEmpty);
  print(name.codeUnits);
  print(name[0]);
  print(name[name.length - 1]);
}

name[0] gives the first character. The last one is at length - 1.

Simple lesson: length counts the characters, and [i] reads one character.

String Interpolation

String interpolation = putting a value inside a string.

  • $name = put a variable's value here.
  • ${expression} = work out an expression, then put its value here.

$ and ${}

void main() {
  var name = 'Ravi';
  var maths = 88;
  var science = 91;
  print('Hello, $name!');
  print('Total: ${maths + science}');
  print('Name in capitals: ${name.toUpperCase()}');
  print('Price: \$5');
}
  • $name.toUpperCase() would NOT work. Dart would put name in, then print .toUpperCase() as text. Use ${...} for anything more than a plain name.
  • \$ prints a real dollar sign.

Simple lesson: use $name for a plain variable and ${...} for anything more.

Concatenation

Concatenation = joining strings end to end.

  • + joins two strings: 'Green' + ' Valley'.
  • Adjacent string literals = two literals written side by side are joined automatically.

Joining strings

void main() {
  var first = 'Green';
  var full = first + ' ' + 'Valley';
  print(full);

  var notice = 'School will close early today '
      'because of the rain.';
  print(notice);

  var marks = 92;
  print('Marks: ' + marks.toString());
}

+ only joins Strings. A number needs toString(), or better, interpolation: 'Marks: $marks'.

Simple lesson: prefer interpolation, use + for short joins, and split long text into adjacent literals.

String Comparison

  • == = are the two strings exactly the same? Capital letters matter.
  • compareTo() = which comes first in dictionary order? Gives -1, 0 or 1.

Comparing strings

void main() {
  print('Asha' == 'Asha');
  print('Asha' == 'asha');
  print('apple'.compareTo('banana'));
  print('mango'.compareTo('apple'));
  print('kiwi'.compareTo('kiwi'));
  print('asha'.toLowerCase() == 'ASHA'.toLowerCase());
}

To compare without caring about case, change both to lower case first.

Simple lesson: == checks exact equality, and compareTo gives dictionary order.

Searching Strings

MethodQuestion
contains(x)is x anywhere inside?
startsWith(x)does it begin with x?
endsWith(x)does it end with x?
indexOf(x)where is the first x? -1 if missing
lastIndexOf(x)where is the last x?

Searching inside text

void main() {
  var email = 'asha.k@greenvalley.edu';
  print(email.contains('@'));
  print(email.startsWith('asha'));
  print(email.endsWith('.edu'));
  print(email.indexOf('@'));
  print(email.lastIndexOf('.'));
  print(email.indexOf('#'));
}

Simple lesson: contains, startsWith and endsWith say yes or no, and indexOf says where.

Extracting Text

substring(start, end) = the characters from start up to (not including) end.

Cut the user name out of an email

Accessing Characters

text[i] gives the character at index i, as a one-letter String.

Simple lesson: substring cuts out a piece by index, and [i] reads one character.

Modifying Strings

Strings never change. These methods give back a new string:

MethodWhat it gives
replaceAll(a, b)every a changed to b
replaceFirst(a, b)only the first a changed
replaceRange(start, end, x)the part from start to end replaced by x
padLeft(n, c)adds c on the left until the length is n
padRight(n, c)adds c on the right until the length is n

Replacing and padding

void main() {
  var notice = 'Holiday on Monday. Monday is a holiday.';
  print(notice.replaceAll('Monday', 'Friday'));
  print(notice.replaceFirst('Monday', 'Friday'));
  print('9876543210'.replaceRange(2, 8, '******'));
  print('7'.padLeft(3, '0'));
  print('Maths'.padRight(10, '.') + '92');
  print('Science'.padRight(10, '.') + '85');
}

padLeft(3, '0') turns roll number 7 into 007. padRight lines up a report card.

Simple lesson: replaceAll swaps text, and padLeft and padRight make text a fixed width.

Case Conversion and Whitespace

  • toUpperCase() / toLowerCase() = all capitals, or all small letters.
  • trim() = removes spaces at both ends.
  • trimLeft() / trimRight() = only at the left, or only at the right.

Cleaning up a typed name

void main() {
  var typed = '   aSHa   ';
  print('[${typed.trim()}]');
  print('[${typed.trimLeft()}]');
  print('[${typed.trimRight()}]');
  var clean = typed.trim().toLowerCase();
  print(clean);
  print(clean[0].toUpperCase() + clean.substring(1));
}

The brackets show where the spaces are. The last line makes "Asha" with a capital first letter.

Simple lesson: trim() removes extra spaces, and the case methods fix capital letters.

Splitting and Joining

  • split(separator) = cuts a string into a List of pieces.
  • join(separator) = the opposite, on a list: glues the pieces into one string.

From text to a list, and back

void main() {
  var csv = 'Asha,Ravi,Priya,Kiran';
  var names = csv.split(',');
  print(names);
  print(names.length);
  print(names.join(' | '));
  print('Hello'.split(''));
  var words = 'Dart is fun'.split(' ');
  print(words.reversed.join(' '));
}

split('') cuts between every character.

String Conversion

toString() turns any value into text (see Data Types): 92.toString() gives '92'.

Simple lesson: split turns text into a list, and join turns a list into text.

StringBuffer

StringBuffer Fundamentals

StringBuffer = a tool for building a long string piece by piece.

Joining with + in a loop makes a brand new string every round. A StringBuffer keeps adding to one place, which is faster.

StringBuffer Operations

MethodWhat it does
write(x)adds x
writeln(x)adds x and a new line
writeAll(list, sep)adds every item, with sep between
clear()empties the buffer
toString()gives the finished string

Building a report card

void main() {
  var marks = {'Maths': 92, 'Science': 85, 'English': 78};
  var report = StringBuffer();
  report.writeln('REPORT CARD');
  report.writeln('-----------');
  marks.forEach((subject, mark) {
    report.write(subject.padRight(10));
    report.writeln(mark);
  });
  report.write('Subjects: ');
  report.writeAll(marks.keys, ', ');
  print(report.toString());
  print('Characters: ${report.length}');
}

Simple lesson: use a StringBuffer to build long text, then call toString() once at the end.

Runes and Unicode

Unicode Characters and Emoji

Unicode = a world-wide list that gives every character a number: A is 65, अ is 2309, 😀 is 128512.

  • Dart strings store text as UTF-16 units.
  • Most characters use one unit.
  • Many emoji use two units, so length counts them as 2.

runes

Rune = one Unicode character code.

Emoji, length and runes

void main() {
  var smile = '😀';
  print(smile.length);
  print(smile.runes.length);
  print(smile.runes.first);
  print('नमस्ते'.length);
  print(String.fromCharCode(65));
  print(String.fromCharCodes([72, 105]));
  print('\u{1F44D} Well done!');
}
  • runes counts real characters, so 😀 is 1 rune.
  • String.fromCharCode(n) = turns a character code into a string.
  • \u{...} = writes a character by its Unicode number.

Never cut a string with substring in the middle of an emoji. Half an emoji shows up as a broken box.

For text with emoji, the characters package handles real letters safely (see Libraries).

Easy way to remember

  • Find: contains, indexOf. Cut: substring, split.
  • Change: replaceAll, toUpperCase, trim, padLeft.
  • Build: interpolation for short text, StringBuffer for long text.

Simple lesson: length counts UTF-16 units, and runes counts real characters.

TL;DR

  1. String = text in quotes. Multi-line: '''...'''. Raw: r'...'.

    • Never changes. Methods give a new string.
  2. Interpolation: $name and ${expression}. Join: +, or adjacent literals.
  3. Compare: == (exact), compareTo (-1, 0, 1).

    • Search: contains, startsWith, endsWith, indexOf, lastIndexOf.
  4. Cut and change: substring, [i], replaceAll, replaceFirst, replaceRange, padLeft, padRight.

    • Clean: toUpperCase, toLowerCase, trim. Split and join: split, join.
  5. StringBuffer = write, writeln, writeAll, clear, toString.

    • Unicode: runes, codeUnits, String.fromCharCode, \u{...}.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
'$name.length'$ takes the whole expressionUse ${name.length}It prints the name, then .length.
name.toUpperCase(); aloneIt changes nameStrings never changeNothing happens. Store the result.
'Total: ' + 92+ joins anything+ needs two StringsA type error.
substring(1, 3) gives 3 charactersThe end index is includedThe end is NOT includedOne character too few.
'Asha' == 'asha' is trueCase does not matter== is exactfalse. Compare lower case versions.
Building text with + in a long loopIt is just as fastIt makes many copiesSlow code. Use a StringBuffer.
Counting emoji with lengthOne emoji = 1Many emoji are 2 UTF-16 unitsWrong counts. Use runes.

Check Yourself

Exercises

What to Remember

  • A string is text in quotes. It never changes, so every method gives a new string.
  • Use $name and ${expression} to put values inside text.
  • contains, indexOf and substring find and cut text.
  • replaceAll, trim, toUpperCase, split and join change and reshape text.
  • Build long text with StringBuffer, and use runes to count real characters.

Next: Date and Time. You will learn to work with dates, times and durations, like exam days and homework deadlines.