OLD | NEW |
| (Empty) |
1 --- | |
2 layout: default | |
3 title: "A Tour of the Dart Libraries" | |
4 description: "Learn how to use each major Dart library feature." | |
5 has-permalinks: true | |
6 --- | |
7 | |
8 # {{ page.title }} | |
9 | |
10 Welcome to the Dart library tour! | |
11 We'll show you how to use the major features in each library | |
12 that comes with Dart. | |
13 | |
14 This tour is just an overview of | |
15 library functionality; it is by no means comprehensive. | |
16 Consult the | |
17 [Dart API reference](http://api.dartlang.org/) | |
18 for the full details about a class or interface. | |
19 | |
20 <aside> | |
21 <div class="alert"> | |
22 <strong>Warning:</strong> | |
23 Expect major changes to the Dart libraries before Dart's | |
24 first release. | |
25 </div> | |
26 </aside> | |
27 | |
28 #### Contents {#toc} | |
29 | |
30 1. [dart:core - Strings, collections, and more](#dartcore---strings-collections-
and-more) | |
31 1. [Collections](#collections) | |
32 1. [Lists](#lists) | |
33 1. [Sets](#sets) | |
34 1. [Common collection methods](#common-collection-methods) | |
35 1. [Maps (aka dictionaries or hashes)](#maps-aka-dictionaries-or-hashes) | |
36 1. [Dates and times](#dates-and-times) | |
37 1. [Utility interfaces](#utility-interfaces) | |
38 1. [Strings and regular expressions](#strings-and-regular-expressions) | |
39 1. [Asynchronous programming](#asynchronous-programming) | |
40 1. [Exceptions](#exceptions) | |
41 1. [dart:math - Math](#dartmath---math) | |
42 1. [dart:html - Using HTML5 APIs](#html) | |
43 1. [Manipulating the DOM](#html-dom) | |
44 1. [WebSockets](#html-websockets) | |
45 1. [dart:isolate - Concurrency with isolates](#dartisolate---concurrency-with-is
olates) | |
46 1. [Isolate concepts](#isolate-concepts) | |
47 1. [Using isolates](#using-isolates) | |
48 1. [Sending messages](#sending-messages) | |
49 1. [Receiving messages](#receiving-messages) | |
50 1. [Receiving replies](#receiving-replies) | |
51 1. [dart:io - File and socket I/O for command-line apps](#dartio---file-and-sock
et-io-for-command-line-apps) | |
52 1. [Files and directories](#files-and-directories) | |
53 1. Sockets (coming soon) | |
54 1. HTTP Server (coming soon) | |
55 1. HTTP Client (coming soon) | |
56 1. Web socket server (coming soon) | |
57 1. [dart:json - Encoding and decoding objects](#json) | |
58 1. [dart:uri - Manipulating URLs](#uri) | |
59 1. [dart:utf - Strings and Unicode](#utf) | |
60 1. [dart:crypto - Hash codes and more](#crypto) | |
61 {:.toc} | |
62 | |
63 ## dart:core - Strings, collections, and more | |
64 | |
65 The Dart core library provides a small but critical set of built-in functionalit
y. | |
66 This library is automatically imported into every Dart program. | |
67 | |
68 ### Collections | |
69 | |
70 Dart ships with a core collections API, which includes interfaces for Lists, | |
71 Maps, and Sets. | |
72 | |
73 #### Lists | |
74 | |
75 A [list](http://api.dartlang.org/dart_core/List.html) in Dart is an ordered | |
76 collection of items, analogous to an array in other languages. | |
77 Lists are zero indexed, and they can contain duplicate items. | |
78 | |
79 The language tour has | |
80 [more information about lists](/docs/language-tour/#lists). | |
81 | |
82 ##### Creating, adding, and removing | |
83 | |
84 As the language tour shows, you can create and initialize lists using literals. | |
85 Alternatively, use one of the [List | |
86 constructors](http://api.dartlang.org/dart_core/List.html#List). The List class | |
87 also provides several methods for adding items to and removing items from lists. | |
88 | |
89 {% highlight dart %} | |
90 // Use a list constructor. | |
91 var vegetables = new List(); | |
92 | |
93 // Or simply use a list literal. | |
94 var fruits = ['apples', 'oranges']; | |
95 | |
96 // Add to a list. | |
97 fruits.add('kiwis'); | |
98 | |
99 // Add multiple items to a list. | |
100 fruits.addAll(['grapes', 'bananas']); | |
101 | |
102 // Get the list length. | |
103 assert(fruits.length == 5); | |
104 | |
105 // Remove a single item. | |
106 var appleIndex = fruits.indexOf('apples'); | |
107 fruits.removeRange(appleIndex, 1); | |
108 assert(fruits.length == 4); | |
109 | |
110 // Remove all elements from a list. | |
111 fruits.clear(); | |
112 assert(fruits.length == 0); | |
113 {% endhighlight %} | |
114 | |
115 ##### Getting and setting items | |
116 | |
117 Lists use zero-based indexing, where 0 | |
118 is the index of the first element, and | |
119 `list.length-1` is the index of the last | |
120 element. Use `indexOf()` to find | |
121 the index of an object in a list. | |
122 | |
123 {% highlight dart %} | |
124 var fruits = ['apples', 'oranges']; | |
125 | |
126 // Access a list item by index. | |
127 assert(fruits[0] == 'apples'); | |
128 | |
129 // Find an item in a list. | |
130 assert(fruits.indexOf('apples') == 0); | |
131 {% endhighlight %} | |
132 | |
133 ##### Sorting | |
134 | |
135 Sort a list using the `sort()` method, and you must provide | |
136 a sorting function that compares two objects. | |
137 The sorting function must | |
138 return < 0 for _smaller_, | |
139 0 for the _same_, and > 0 for _bigger_. | |
140 | |
141 {% highlight dart %} | |
142 var fruits = ['bananas', 'apples', 'oranges']; | |
143 | |
144 // Sort a list. | |
145 fruits.sort((a, b) => a.compareTo(b)); | |
146 assert(fruits[1] == 'bananas'); | |
147 {% endhighlight %} | |
148 | |
149 ##### Generics | |
150 | |
151 Lists are parameterized types, so you can specify the type that a list | |
152 should contain. | |
153 | |
154 {% highlight dart %} | |
155 // This list should contain only strings. | |
156 var fruits = new List<String>(); | |
157 | |
158 fruits.add('apples'); | |
159 var fruit = fruits[0]; | |
160 assert(fruit is String); | |
161 | |
162 // Generates static analysis warning; num is not a string. | |
163 fruits.add(5); // BAD: Throws exception in checked mode. | |
164 {% endhighlight %} | |
165 | |
166 ##### More information | |
167 | |
168 Refer to the full | |
169 [List API docs](http://api.dartlang.org/dart_core/List.html) | |
170 for a full list of methods. | |
171 | |
172 [Back to contents.](#toc) | |
173 {:.up-to-toc} | |
174 | |
175 #### Sets | |
176 | |
177 A [set](http://api.dartlang.org/dart_core/Set.html) | |
178 in Dart | |
179 is an unordered collection of unique items. | |
180 Because a set is unordered, | |
181 you can't get a set's items by index (position). | |
182 | |
183 ##### Adding and removing | |
184 | |
185 {% highlight dart %} | |
186 var ingredients = new Set(); | |
187 ingredients.addAll(['gold', 'titanium', 'xenon']); | |
188 assert(ingredients.length == 3); | |
189 | |
190 // Adding a duplicate item has no effect. | |
191 ingredients.add('gold'); | |
192 assert(ingredients.length == 3); | |
193 | |
194 // Remove an item from a set. | |
195 ingredients.remove('gold'); | |
196 assert(ingredients.length == 2); | |
197 {% endhighlight %} | |
198 | |
199 ##### Checking membership | |
200 | |
201 Use `contains()` and `containsAll()` to check whether | |
202 one or more objects are in a set. | |
203 | |
204 {% highlight dart %} | |
205 var ingredients = new Set(); | |
206 ingredients.addAll(['gold', 'titanium', 'xenon']); | |
207 | |
208 // Check whether an item is in the set. | |
209 assert(ingredients.contains('titanium') == true); | |
210 | |
211 // Check whether all the items are in the set. | |
212 assert(ingredients.containsAll(['titanium', 'xenon']) == true); | |
213 {% endhighlight %} | |
214 | |
215 ##### Intersection and subset | |
216 | |
217 An intersection is a set whose items are in two other sets. | |
218 A subset has all of its items included | |
219 in another, potentially larger, collection. | |
220 | |
221 {% highlight dart %} | |
222 var ingredients = new Set(); | |
223 ingredients.addAll(['gold', 'titanium', 'xenon']); | |
224 | |
225 // Create the intersection of two sets. | |
226 var nobleGases = new Set.from(['xenon', 'argon']); | |
227 var intersection = ingredients.intersection(nobleGases); | |
228 assert(intersection.length == 1); | |
229 assert(intersection.contains('xenon')); | |
230 | |
231 // Check whether this set is a subset of another collection. | |
232 // That is, does another collection contains all the items of this set? | |
233 var allElements = ['hydrogen', 'helium', 'lithium', 'beryllium', | |
234 'gold', 'titanium', 'xenon' /* all the rest */]; | |
235 assert(ingredients.isSubsetOf(allElements) == true); | |
236 {% endhighlight %} | |
237 | |
238 ##### More information | |
239 | |
240 Refer to the full | |
241 [Set API docs](http://api.dartlang.org/dart_core/Set.html) | |
242 for a full list of methods. | |
243 | |
244 [Back to contents.](#toc) | |
245 {:.up-to-toc} | |
246 | |
247 #### Common collection methods | |
248 | |
249 Both List and Set extend the | |
250 [Collection](http://api.dartlang.org/dart_core/Collection.html) interface. | |
251 As such, they share common functionality found in all collections. | |
252 | |
253 The following examples work with any object that implements Collection. | |
254 | |
255 ##### Checking whether a collection has items | |
256 | |
257 {% highlight dart %} | |
258 var teas = ['green', 'black', 'chamomile', 'earl grey']; | |
259 | |
260 // Use isEmpty() to check whether a collection has no items. | |
261 assert(teas.isEmpty() == false); | |
262 {% endhighlight %} | |
263 | |
264 ##### Applying a function to each item | |
265 | |
266 {% highlight dart %} | |
267 var teas = ['green', 'black', 'chamomile', 'earl grey']; | |
268 | |
269 // Use forEach() to apply a function to every item in a collection. | |
270 teas.forEach((tea) => print('I drink $tea')); | |
271 | |
272 // Use map() to create a new collection by applying a function to each | |
273 // item and collecting the results. | |
274 var loudTeas = teas.map((tea) => tea.toUpperCase()); | |
275 assert(loudTeas.some((tea) => tea == 'GREEN')); | |
276 {% endhighlight %} | |
277 | |
278 ##### Filtering and checking items | |
279 | |
280 Use `forEach()` and `map()` to apply a function to each | |
281 element of the collection. Use `some()` and `every()` | |
282 to check whether some or all items in a collection | |
283 match a condition. | |
284 | |
285 {% highlight dart %} | |
286 var teas = ['green', 'black', 'chamomile', 'earl grey']; | |
287 | |
288 // Chamomile is not caffeinated. | |
289 isDecaffeinated(String teaName) => teaName == 'chamomile'; | |
290 | |
291 // Use filter() to create a new collection with only the items | |
292 // that return true from the provided function. | |
293 var decaffeinatedTeas = teas.filter((tea) => isDecaffeinated(tea)); | |
294 // Or teas.filter(isDecaffeinated) | |
295 | |
296 // Use some() to check whether at least one item in the collection | |
297 // satisfies a condition. | |
298 assert(teas.some(isDecaffeinated) == true); | |
299 | |
300 // Use every() to check whether all the items in a collection | |
301 // satisfy a condition. | |
302 assert(teas.every(isDecaffeinated) == false); | |
303 {% endhighlight %} | |
304 | |
305 ##### More information | |
306 | |
307 Refer to the full | |
308 [Collection API docs](http://api.dartlang.org/dart_core/Collection.html) | |
309 for a full list of methods. | |
310 | |
311 [Back to contents.](#toc) | |
312 {:.up-to-toc} | |
313 | |
314 #### Maps (aka dictionaries or hashes) | |
315 | |
316 The [Map](http://api.dartlang.org/dart_core/Map.html) | |
317 interface, commonly known as a _dictionary_ or _hash_, | |
318 is an unordered collection of key-value pairs. | |
319 Maps associate a key to some value for easy retrieval. | |
320 Unlike in JavaScript, Dart objects are not maps. | |
321 | |
322 The language tour has more | |
323 [information about maps](/docs/language-tour/#maps). | |
324 | |
325 <aside> | |
326 <div class="alert alert-info"> | |
327 <strong>Note:</strong> | |
328 The Map | |
329 interface does not extend Collection. | |
330 </div> | |
331 </aside> | |
332 | |
333 ##### Creating maps | |
334 | |
335 You can declare a map using a terse literal syntax, | |
336 or you can use a traditional constructor. | |
337 | |
338 {% highlight dart %} | |
339 // Map literals use strings as keys. | |
340 var hawaiianBeaches = { | |
341 "oahu" : ['waikiki', 'kailua', 'waimanalo'], | |
342 "big island" : ['wailea bay', 'pololu beach'], | |
343 "kauai" : ['hanalei', 'poipu'] | |
344 }; | |
345 | |
346 // Maps can be built from a constructor. | |
347 var searchTerms = new Map(); | |
348 | |
349 // Maps are parameterized types; you can specify what types | |
350 // the key and value should be. | |
351 var nobleGases = new Map<int, String>(); | |
352 {% endhighlight %} | |
353 | |
354 ##### Adding, retrieving, and removing items | |
355 | |
356 You add, get, and set map items using the bracket syntax. | |
357 Use `remove()` to remove a key and its value from a map. | |
358 | |
359 {% highlight dart %} | |
360 var nobleGases = new Map<int, String>(); | |
361 | |
362 // Maps from constructors can use any Hashable object as a key; | |
363 // for example, int implements Hashable. | |
364 nobleGases[54] = 'xenon'; | |
365 | |
366 // Associate a key with a value. | |
367 nobleGases[54] = 'xenon'; | |
368 | |
369 // Retrieve a value with a key. | |
370 assert(nobleGases[54] == 'xenon'); | |
371 | |
372 // Check whether a map contains a key. | |
373 assert(nobleGases.containsKey(54) == true); | |
374 | |
375 // Add a key-value pair only if the key doesn't yet exist in the map. | |
376 var value = nobleGases.putIfAbsent(36, () => 'krypton'); | |
377 assert(value == 'krypton'); | |
378 | |
379 // Remove a key and its value. | |
380 nobleGases.remove(54); | |
381 assert(nobleGases.containsKey(54) == false); | |
382 {% endhighlight %} | |
383 | |
384 ##### Iterating through a map | |
385 | |
386 You can retrieve all the values or all the keys from | |
387 a map. You can also iterate through the key-value | |
388 pairs. | |
389 | |
390 {% highlight dart %} | |
391 var hawaiianBeaches = { | |
392 "oahu" : ['waikiki', 'kailua', 'waimanalo'], | |
393 "big island" : ['wailea bay', 'pololu beach'], | |
394 "kauai" : ['hanalei', 'poipu'] | |
395 }; | |
396 | |
397 // Get all the keys as an unordered collection. | |
398 var keys = hawaiianBeaches.getKeys(); | |
399 | |
400 assert(keys.length == 3); | |
401 assert(new Set.from(keys).contains('oahu') == true); | |
402 | |
403 // Get all the values as an unordered collection. | |
404 var values = hawaiianBeaches.getValues(); | |
405 assert(values.length == 3); | |
406 assert(values.some((v) => v.indexOf('waikiki') != -1) == true); | |
407 | |
408 // Iterate through the key-value pairs. | |
409 // NOTE: Do not depend on iteration order. | |
410 hawaiianBeaches.forEach((k,v) { | |
411 print("I want to visit $k and swim at $v"); | |
412 // I want to visit oahu and swim at [waikiki, kailua, waimanalo] | |
413 }); | |
414 {% endhighlight %} | |
415 | |
416 ##### More information | |
417 | |
418 Refer to the full | |
419 [Map API docs](http://api.dartlang.org/dart_core/Map.html) | |
420 for a full list of methods. | |
421 | |
422 [Back to contents.](#toc) | |
423 {:.up-to-toc} | |
424 | |
425 ### Dates and times | |
426 | |
427 A [Date](http://api.dartlang.org/dart_core/Date.html) object is a point in time. | |
428 The time is either UTC or the local time zone. | |
429 | |
430 #### Constructing dates | |
431 | |
432 {% highlight dart %} | |
433 // Get the current date and time. | |
434 var now = new Date.now(); | |
435 | |
436 // Create a new Date with the local time zone. | |
437 var y2k = new Date(2000, 1, 1, 0, 0, 0, 0); | |
438 | |
439 // You can also use named parameters. | |
440 y2k = new Date(2000, month: 1, day: 1, hour: 0, minute: 0, second: 0, | |
441 millisecond: 0); | |
442 | |
443 // Specify all the parts of a date as a UTC time. | |
444 y2k = new Date(2000, 1, 1, 0, 0, 0, 0, isUtc: true); | |
445 | |
446 // Specify a UTC date and time in milliseconds since the Unix epoch. | |
447 y2k = new Date.fromMillisecondsSinceEpoch(1336017592000, isUtc: true); | |
448 | |
449 // Parse an ISO 8601 date. | |
450 y2k = new Date.fromString('2000-01-01T00:00:00Z'); | |
451 {% endhighlight %} | |
452 | |
453 #### The epoch | |
454 | |
455 The `millisecondsSinceEpoch` getter on a date returns the number | |
456 of milliseconds since the epoch. | |
457 | |
458 {% highlight dart %} | |
459 var y2k = new Date.fromString('2000-01-01T00:00:00Z'); | |
460 assert(y2k.millisecondsSinceEpoch == 946684800000); | |
461 {% endhighlight %} | |
462 | |
463 #### Calculations | |
464 | |
465 Use the [Duration](http://api.dartlang.org/dart_core/Duration.html) class to | |
466 calculate the difference between two dates | |
467 and to shift a date's time forward or backwards. | |
468 | |
469 {% highlight dart %} | |
470 var y2k = new Date.fromString('2000-01-01T00:00:00Z'); | |
471 | |
472 // Add one year. | |
473 var y2001 = y2k.add(const Duration(366, 0, 0, 0, 0)); | |
474 assert(y2001.year == 2001); | |
475 | |
476 // Subtract 30 days. | |
477 var december2000 = y2001.subtract(const Duration(30, 0 ,0, 0, 0)); | |
478 assert(december2000.year == 2000); | |
479 assert(december2000.month == 12); | |
480 | |
481 // Calculate the difference between two dates. | |
482 // Returns a Duration object. | |
483 var duration = y2001.difference(y2k); | |
484 assert(duration.inDays == 366); // y2k was a leap year. | |
485 {% endhighlight %} | |
486 | |
487 #### More information | |
488 | |
489 Refer to the full | |
490 [Date API docs](http://api.dartlang.org/dart_core/Date.html) and | |
491 [Duration API docs](http://api.dartlang.org/dart_core/Duration.html) | |
492 for a full list of methods. | |
493 | |
494 [Back to contents.](#toc) | |
495 {:.up-to-toc} | |
496 | |
497 ### Utility interfaces | |
498 | |
499 The core library contains various utility interfaces, useful for | |
500 sorting, mapping values, and iterating. | |
501 | |
502 #### Comparing objects | |
503 | |
504 Use the [Comparable](http://api.dartlang.org/dart_core/Comparable.html) | |
505 interface to indicate that an object can be compared | |
506 to another object, usually for sorting. The `compareTo` method | |
507 returns < 0 for _smaller_, | |
508 0 for the _same_, and > 0 for _bigger_. | |
509 | |
510 {% highlight dart %} | |
511 class Line implements Comparable { | |
512 final length; | |
513 const Line(this.length); | |
514 int compareTo(Line other) => length - other.length; | |
515 } | |
516 | |
517 main() { | |
518 var short = const Line(1); | |
519 var long = const Line(100); | |
520 assert(short.compareTo(long) < 0); | |
521 } | |
522 {% endhighlight %} | |
523 | |
524 [Back to contents.](#toc) | |
525 {:.up-to-toc} | |
526 | |
527 #### Implementing map keys | |
528 | |
529 The default implementation of Map requires map keys to implement Hashable. | |
530 The [Hashable](http://api.dartlang.org/dart_core/Hashable.html) interface | |
531 indicates that an object can provide an integer | |
532 hash code. | |
533 | |
534 Objects that are equal (via ==) must have identical hash codes. | |
535 A hash code doesn't have to be unique, but it should | |
536 be well distributed. | |
537 | |
538 {% highlight dart %} | |
539 class Person implements Hashable { | |
540 String firstName, lastName; | |
541 | |
542 Person(this.firstName, this.lastName); | |
543 | |
544 // Strategy from Effective Java, Chapter 11. | |
545 int hashCode() { | |
546 int result = 17; | |
547 result = 37 * result + firstName.hashCode(); | |
548 result = 37 * result + lastName.hashCode(); | |
549 return result; | |
550 } | |
551 | |
552 // Always implement operator== if class implements Hashable. | |
553 bool operator==(other) { | |
554 if (other == null) return false; | |
555 if (other === this) return true; | |
556 return (other.firstName == firstName && other.lastName == lastName); | |
557 } | |
558 } | |
559 | |
560 main() { | |
561 var p1 = new Person('bob', 'smith'); | |
562 var p2 = new Person('bob', 'smith'); | |
563 assert(p1.hashCode() == p2.hashCode()); | |
564 } | |
565 {% endhighlight %} | |
566 | |
567 ##### More information | |
568 | |
569 Refer to the full | |
570 [Hashable API docs](http://api.dartlang.org/dart_core/Hashable.html) | |
571 for a full list of methods. | |
572 | |
573 [Back to contents.](#toc) | |
574 {:.up-to-toc} | |
575 | |
576 #### Iteration | |
577 | |
578 Two interfaces contribute to iteration abilities in Dart, allowing objects | |
579 to work in for-in loops. Implementing the | |
580 [Iterable](http://api.dartlang.org/dart_core/Iterable.html) | |
581 interface signals that an object can provide an Iterator. | |
582 The [Iterator](http://api.dartlang.org/dart_core/Iterator.html) interface | |
583 defines the actual iteration ability. | |
584 | |
585 {% highlight dart %} | |
586 class Process { | |
587 // Represents a process... | |
588 } | |
589 | |
590 class ProcessIterator implements Iterator<Process> { | |
591 Process next() { | |
592 // Return the next process if possible; but if not: | |
593 throw new NoMoreElementsException(); | |
594 } | |
595 bool hasNext() { | |
596 // True if calling next() would return a process. | |
597 return false; | |
598 } | |
599 } | |
600 | |
601 // A mythical class that lets you iterate through all processes. | |
602 class Processes implements Iterable<Process> { | |
603 Iterator<Process> iterator() { | |
604 return new ProcessIterator(); | |
605 } | |
606 } | |
607 | |
608 main() { | |
609 // Objects that implement Iterable can be used with for-in. | |
610 for (var process in new Processes()) { | |
611 // Do something with the process. | |
612 } | |
613 } | |
614 {% endhighlight %} | |
615 | |
616 ##### More information | |
617 | |
618 Refer to the full | |
619 [Iterable API docs](http://api.dartlang.org/dart_core/Iterable.html) | |
620 and | |
621 [Iterator API docs](http://api.dartlang.org/dart_core/Iterator.html) | |
622 for a full list of methods. | |
623 | |
624 [Back to contents.](#toc) | |
625 {:.up-to-toc} | |
626 | |
627 ### Strings and regular expressions | |
628 | |
629 A [String](http://api.dartlang.org/dart_core/String.html) is | |
630 an immutable, ordered list of 32-bit Unicode character codes. | |
631 You can use regular expressions to | |
632 search within strings and to replace parts of strings. | |
633 | |
634 The [Pattern](http://api.dartlang.org/dart_core/Pattern.html) | |
635 interface is implemented by both String and | |
636 [RegExp](http://api.dartlang.org/dart_core/RegExp.html), | |
637 and is used for methods like | |
638 [split](http://api.dartlang.org/dart_core/String.html#split) and | |
639 [contains](http://api.dartlang.org/dart_core/String.html#contains). | |
640 | |
641 The language tour has | |
642 [more information about strings](/docs/language-tour/#strings). | |
643 | |
644 #### Searching inside a string | |
645 | |
646 You can find particular locations within a string, as well as check | |
647 whether a string begins with or ends with a particular pattern. | |
648 | |
649 {% highlight dart %} | |
650 // Check whether a string contains another string. | |
651 assert("Never odd or even".contains("odd") == true); | |
652 | |
653 // Does a string start with another string? | |
654 assert("Never odd or even".startsWith("Never") == true); | |
655 | |
656 // Does a string end with another string? | |
657 assert("Never odd or even".endsWith("even") == true); | |
658 | |
659 // Find the location of a string inside a string. | |
660 assert("Never odd or even".indexOf("odd") == 6); | |
661 {% endhighlight %} | |
662 | |
663 #### Extracting data from a string | |
664 | |
665 You can get the individual characters (as Strings) | |
666 or individual character codes (as ints) from a string. | |
667 | |
668 You can also extract a substring or split a string | |
669 into a list of substrings. | |
670 | |
671 {% highlight dart %} | |
672 // Grab a substring. | |
673 assert("Never odd or even".substring(6, 9) == 'odd'); | |
674 | |
675 // Split a string using a string pattern. | |
676 var parts = "structured web apps".split(" "); | |
677 assert(parts.length == 3); | |
678 assert(parts[0] == 'structured'); | |
679 | |
680 // Get the character (as a string) by index. | |
681 assert("Never odd or even"[0] == "N"); | |
682 | |
683 // Use splitChars() to get a list of all characters (as Strings); | |
684 // good for iterating. | |
685 for (var char in "hello".splitChars()) { | |
686 print(char); | |
687 } | |
688 | |
689 // Get the char code at an index. | |
690 assert("Never odd or even".charCodeAt(0) == 78); | |
691 | |
692 // Get all the char codes as a list of integers. | |
693 var charCodes = "Never odd or even".charCodes(); | |
694 assert(charCodes.length == 17); | |
695 assert(charCodes[0] == 78); | |
696 {% endhighlight %} | |
697 | |
698 #### Converting to uppercase or lowercase | |
699 | |
700 Easily convert strings to their uppercase and lowercase variants. | |
701 | |
702 {% highlight dart %} | |
703 // Convert to uppercase. | |
704 assert("structured web apps".toUpperCase() == 'STRUCTURED WEB APPS'); | |
705 | |
706 // Convert to lowercase. | |
707 assert("STRUCTURED WEB APPS".toLowerCase() == 'structured web apps'); | |
708 {% endhighlight %} | |
709 | |
710 #### Trimming and empty strings | |
711 | |
712 Remove all leading and trailing white space with trim(). | |
713 To check whether a string is empty (length is zero), use isEmpty(). | |
714 | |
715 {% highlight dart %} | |
716 // Trim a string. | |
717 assert(' hello '.trim() == 'hello'); | |
718 | |
719 // Check whether a string is empty. | |
720 assert(''.isEmpty() == true); | |
721 | |
722 // Strings with only white space are not empty. | |
723 assert(' '.isEmpty() == false); | |
724 {% endhighlight %} | |
725 | |
726 #### Regular expressions | |
727 | |
728 The [RegExp](http://api.dartlang.org/dart_core/RegExp.html) | |
729 interface provides the same capabilities as JavaScript | |
730 regular expressions. Use regular expressions for efficient searching | |
731 and pattern matching of strings. | |
732 | |
733 {% highlight dart %} | |
734 // A regular expression for one or more digits. | |
735 var numbers = const RegExp(r'\d+'); | |
736 | |
737 var allCharacters = "llamas live fifteen to twenty years"; | |
738 var someDigits = "llamas live 15 to 20 years"; | |
739 | |
740 // contains() can use a regular expression. | |
741 assert(allCharacters.contains(numbers) == false); | |
742 assert(someDigits.contains(numbers) == true); | |
743 | |
744 // Replace every match with another string. | |
745 var exedOut = someDigits.replaceAll(numbers, "XX"); | |
746 assert(exedOut == 'llamas live XX to XX years'); | |
747 {% endhighlight %} | |
748 | |
749 You can work directly with the RegExp class, too. | |
750 The [Match](http://api.dartlang.org/dart_core/Match.html) interface | |
751 provides access to a regular expression match. | |
752 | |
753 {% highlight dart %} | |
754 var numbers = const RegExp(r'\d+'); | |
755 var someDigits = "llamas live 15 to 20 years"; | |
756 | |
757 // Check whether the reg exp has a match in a string. | |
758 assert(numbers.hasMatch(someDigits) == true); | |
759 | |
760 // Loop through all matches. | |
761 for (var match in numbers.allMatches(someDigits)) { | |
762 print(match.group(0)); // 15, then 20. | |
763 } | |
764 {% endhighlight %} | |
765 | |
766 #### More information | |
767 | |
768 Refer to the full | |
769 [String API docs](http://api.dartlang.org/dart_core/String.html) | |
770 for a full list of methods. | |
771 Also see the API docs for | |
772 [RegExp](http://api.dartlang.org/dart_core/RegExp.html) and | |
773 [Match](http://api.dartlang.org/dart_core/Match.html). | |
774 | |
775 [Back to contents.](#toc) | |
776 {:.up-to-toc} | |
777 | |
778 ### Asynchronous programming | |
779 | |
780 Async programming often uses callback functions, | |
781 but Dart provides an alternative: | |
782 the [Future](http://api.dartlang.org/dart_core/Future.html) interface. | |
783 A Future is | |
784 like a promise for a result to be provided "sometime in the future." | |
785 | |
786 You have the option of using a | |
787 [Completer](http://api.dartlang.org/dart_core/Completer.html) | |
788 to produce a Future | |
789 and, later, to supply a value to the Future. | |
790 | |
791 {% highlight dart %} | |
792 Future<bool> longExpensiveSearch() { | |
793 var completer = new Completer(); | |
794 // Perform exhaustive search. | |
795 // ... | |
796 // Sometime later, | |
797 // found it!! | |
798 completer.complete(true); | |
799 return completer.future; | |
800 } | |
801 | |
802 void main() { | |
803 var result = longExpensiveSearch(); //returns immediately | |
804 | |
805 // result.then() returns immediately. | |
806 result.then((success) { | |
807 // The following code executes when the operation is complete. | |
808 print("The item was found: $success"); | |
809 }); | |
810 } | |
811 {% endhighlight %} | |
812 | |
813 #### Chaining multiple asynchronous methods | |
814 | |
815 The Future interface specifies a chain() method, which is a useful way | |
816 to specify that multiple async methods run in a certain order. | |
817 The chain() method takes a single function as a parameter, which | |
818 receives the value from the previous Future in the chain. | |
819 The function passed to chain() must itself return a Future. | |
820 | |
821 {% highlight dart %} | |
822 Future expensiveWork() { | |
823 // ... | |
824 } | |
825 | |
826 Future lengthyComputation() { | |
827 // ... | |
828 } | |
829 | |
830 Future costlyQuery() { | |
831 // ... | |
832 } | |
833 | |
834 Future result = costlyQuery(); | |
835 result.handleException((exception) => print("DOH!")); | |
836 | |
837 result.chain((value) => expensiveWork()) | |
838 .chain((value) => lengthyComputation()) | |
839 .then((value) => print("done!")); | |
840 {% endhighlight %} | |
841 | |
842 In the above example, the methods run in the following order: | |
843 | |
844 1. costlyQuery() | |
845 1. expensiveWork() | |
846 1. lengthyComputation() | |
847 | |
848 In addition to the chain() method, the Future interface also defines a | |
849 transform() method. Use transform() when you only need to manipulate the | |
850 returned value, returning a new value immediately. | |
851 Use chain() when you need to start | |
852 another asynchronous operation, returning a Future. | |
853 | |
854 #### Waiting for multiple futures | |
855 | |
856 Sometimes your algorithm needs to initiate many asynchronous methods | |
857 and wait for each one to complete before continuing. Use the Futures class | |
858 to manage multiple Futures and wait for them all to complete. | |
859 | |
860 {% highlight dart %} | |
861 Future deleteDone = deleteLotsOfFiles(); | |
862 Future copyDone = copyLotsOfFiles(); | |
863 Future checksumDone = checksumLotsOfOtherFiles(); | |
864 | |
865 Futures.wait([deleteDone, copyDone, checksumDone]).then((List values) { | |
866 print('Done with all the long steps'); | |
867 }); | |
868 {% endhighlight %} | |
869 | |
870 #### More information | |
871 | |
872 Refer to the API docs for | |
873 [Future](http://api.dartlang.org/dart_core/Future.html), | |
874 [Futures](http://api.dartlang.org/dart_core/Futures.html), and | |
875 [Completer](http://api.dartlang.org/dart_core/Completer.html) | |
876 for a full list of methods. | |
877 | |
878 [Back to contents.](#toc) | |
879 {:.up-to-toc} | |
880 | |
881 ### Exceptions | |
882 | |
883 The Dart core library defines many common exceptions, | |
884 all extending the base | |
885 [Exception](http://api.dartlang.org/dart_core/Exception.html) | |
886 interface. | |
887 | |
888 Learn more about throwing and catching exceptions | |
889 in the [Exceptions section](/docs/language-tour/#exceptions) | |
890 of the language tour. | |
891 | |
892 #### Common exceptions | |
893 | |
894 Some of the most common exceptions include: | |
895 | |
896 [NoSuchMethodException](http://api.dartlang.org/dart_core/NoSuchMethodException.
html) | |
897 : Thrown when a receiving object does not implement a method. | |
898 | |
899 [NullPointerException](http://api.dartlang.org/dart_core/NullPointerException.ht
ml) | |
900 : Thrown when the program tries to call a method or access a field of a | |
901 null object. | |
902 | |
903 [IllegalArgumentException](http://api.dartlang.org/dart_core/IllegalArgumentExce
ption.html) | |
904 : Can be thrown by a method that encounters an unexpected argument. | |
905 | |
906 | |
907 #### Defining your own exception | |
908 | |
909 Throwing an application-specific exception is a common way to indicate | |
910 that an error has occurred. You can define a custom exception | |
911 by implementing the Exception interface. | |
912 | |
913 {% highlight dart %} | |
914 class FooException implements Exception { | |
915 final String msg; | |
916 const FooException([this.msg]); | |
917 String toString() => msg == null ? 'FooException' : msg; | |
918 } | |
919 {% endhighlight %} | |
920 | |
921 ### More information | |
922 | |
923 See the | |
924 [Exception API docs](http://api.dartlang.org/dart_core/Exception.html). | |
925 | |
926 [Back to contents.](#toc) | |
927 {:.up-to-toc} | |
928 | |
929 ## dart:math - Math | |
930 | |
931 The [Math](http://api.dartlang.org/dart_math/index.html) library | |
932 provides common functionality such as sine and cosine, | |
933 maximum and minimum, | |
934 string-to-number conversion, | |
935 and constants such as _pi_ and _e_. | |
936 | |
937 ### Importing the Math library | |
938 | |
939 Math functionality is in the `dart:math` library. | |
940 | |
941 {% highlight dart %} | |
942 #import('dart:math'); | |
943 | |
944 main() { | |
945 // Do fun math stuff. | |
946 } | |
947 {% endhighlight %} | |
948 | |
949 ### Converting strings to numbers | |
950 | |
951 You can convert a string into either an integer or double with the Math class. | |
952 | |
953 {% highlight dart %} | |
954 #import('dart:math'); | |
955 | |
956 main() { | |
957 assert(parseInt('42') == 42); | |
958 assert(parseDouble("0.50") == 0.5); | |
959 } | |
960 {% endhighlight %} | |
961 | |
962 ### Converting numbers to strings | |
963 | |
964 Use the toString() method (defined by | |
965 [Object](http://api.dartlang.org/dart_core/Object.html)) | |
966 to convert an int or double to a string. | |
967 | |
968 To specify the number of digits to the right of the decimal, | |
969 use toStringAsFixed() | |
970 (defined by [num](http://api.dartlang.org/dart_core/num.html)). | |
971 To specify the number of significant digits in the string, | |
972 use toStringAsPrecision(). | |
973 | |
974 {% highlight dart %} | |
975 // Convert an int to a string. | |
976 assert(42.toString() == '42'); | |
977 | |
978 // Convert a double to a string. | |
979 assert(123.456.toString() == '123.456'); | |
980 | |
981 // Specify the number of digits after the decimal. | |
982 assert(123.456.toStringAsFixed(2) == '123.46'); | |
983 | |
984 // Specify the number of significant figures. | |
985 assert(123.456.toStringAsPrecision(2) == '1.2e+2'); | |
986 {% endhighlight %} | |
987 | |
988 ### Trigonometry | |
989 | |
990 Use the Math library for the basic trigonometric functions. | |
991 | |
992 <aside> | |
993 <div class="alert alert-info"> | |
994 <strong>Tip:</strong> | |
995 These methods use radians, not degrees! | |
996 </div> | |
997 </aside> | |
998 | |
999 {% highlight dart %} | |
1000 #import('dart:math'); | |
1001 | |
1002 main() { | |
1003 // Cosine | |
1004 assert(cos(PI) == -1.0); | |
1005 | |
1006 // Sine | |
1007 var degrees = 30; | |
1008 var radians = degrees * (PI / 180); | |
1009 // radians is now 0.52359. | |
1010 var sinOf30degrees = sin(radians); | |
1011 | |
1012 // Truncate the decimal places to 2. | |
1013 assert(parseDouble(sinOf30degrees.toStringAsPrecision(2)) == 0.5); | |
1014 } | |
1015 {% endhighlight %} | |
1016 | |
1017 ### Maximum and mininum | |
1018 | |
1019 The Math library provides optimized max and min methods. | |
1020 | |
1021 {% highlight dart %} | |
1022 #import('dart:math'); | |
1023 | |
1024 main() { | |
1025 assert(max(1, 1000) == 1000); | |
1026 assert(min(1, -1000) == -1000); | |
1027 } | |
1028 {% endhighlight %} | |
1029 | |
1030 ### Math constants | |
1031 | |
1032 Find your favorite constants—_pi_, _e_, and more—in | |
1033 the Math library. | |
1034 | |
1035 {% highlight dart %} | |
1036 // See the Math class for additional constants. | |
1037 | |
1038 #import('dart:math'); | |
1039 | |
1040 main() { | |
1041 print(E); // 2.718281828459045 | |
1042 print(PI); // 3.141592653589793 | |
1043 print(SQRT2); // 1.4142135623730951 | |
1044 } | |
1045 {% endhighlight %} | |
1046 | |
1047 ### Random numbers | |
1048 | |
1049 Generate random numbers with the Random class. | |
1050 You can optionally provide a seed to the Random | |
1051 constructor. | |
1052 | |
1053 {% highlight dart %} | |
1054 #import('dart:math'); | |
1055 | |
1056 main() { | |
1057 var random = new Random(); | |
1058 random.nextDouble(); // Between 0.0 and 0.1. | |
1059 random.nextInt(10); // Between 0 and 9. | |
1060 } | |
1061 {% endhighlight %} | |
1062 | |
1063 You can even generate random booleans. | |
1064 | |
1065 {% highlight dart %} | |
1066 #import('dart:math'); | |
1067 | |
1068 main() { | |
1069 var random = new Random(); | |
1070 random.nextBoolean(); // true or false | |
1071 } | |
1072 {% endhighlight %} | |
1073 | |
1074 ### More information | |
1075 | |
1076 Refer to the full | |
1077 [Math API docs](http://api.dartlang.org/dart_math/index.html) | |
1078 for a full list of methods. | |
1079 Also see the API docs for | |
1080 [num](http://api.dartlang.org/dart_core/num.html), | |
1081 [int](http://api.dartlang.org/dart_core/int.html), | |
1082 and | |
1083 [double](http://api.dartlang.org/dart_core/double.html). | |
1084 | |
1085 [Back to contents.](#toc) | |
1086 {:.up-to-toc} | |
1087 | |
1088 ## dart:html - Using HTML5 APIs {#html} | |
1089 | |
1090 {% render library-tour/html.markdown %} | |
1091 {% render library-tour/html-dom.markdown %} | |
1092 {% render library-tour/html-websockets.markdown %} | |
1093 | |
1094 ### More information | |
1095 | |
1096 Refer to the API docs for | |
1097 [dart:html](http://api.dartlang.org/html.html). | |
1098 | |
1099 [Back to contents.](#toc) | |
1100 {:.up-to-toc} | |
1101 | |
1102 | |
1103 ## dart:isolate - Concurrency with isolates | |
1104 | |
1105 {% render library-tour/isolates.markdown %} | |
1106 | |
1107 ### More information | |
1108 | |
1109 Refer to the API docs for | |
1110 [isolates](http://api.dartlang.org/dart_isolate.html). | |
1111 | |
1112 [Back to contents.](#toc) | |
1113 {:.up-to-toc} | |
1114 | |
1115 ## dart:io - File and socket I/O for command-line apps | |
1116 | |
1117 The [dart:io library](http://api.dartlang.org/io.html) provides | |
1118 file and socket capabilities | |
1119 for the Dart VM when running from the command line. These libraries | |
1120 are not yet available to Dart programs that target the web browser. | |
1121 | |
1122 In general, the dart:io library implements and promotes an | |
1123 asynchronous API. Synchronous | |
1124 methods can easily block the main loop, making | |
1125 it difficult to scale server applications. Therefore, most operations | |
1126 return results via callbacks or Future objects, a pattern common | |
1127 with modern server platforms such as Node.js. | |
1128 | |
1129 The few synchronous methods | |
1130 in the dart:io library | |
1131 are clearly marked with a Sync suffix on the method name. | |
1132 We don't cover them here. | |
1133 | |
1134 ### Importing the I/O library | |
1135 | |
1136 I/O functionality is in the `dart:io` library. | |
1137 | |
1138 {% highlight dart %} | |
1139 #import('dart:io'); | |
1140 | |
1141 main() { | |
1142 // The app | |
1143 } | |
1144 {% endhighlight %} | |
1145 | |
1146 ### Files and directories | |
1147 | |
1148 Command-line Dart applications can read and write files and browse directories. | |
1149 You have two choices for reading the contents of a file: | |
1150 all at once, or streaming. | |
1151 Reading a file all at once requires enough memory | |
1152 to store all the contents of the file. | |
1153 If the file is very large or you want to process it while reading it, | |
1154 you should use a [stream](#streaming-file-contents). | |
1155 | |
1156 #### Reading a file as text | |
1157 | |
1158 When reading a text file, you can read the entire file | |
1159 contents with `readAsText()`. When the individual lines are | |
1160 important, you can use `readAsLines()`. In both cases, | |
1161 a Future object is returned that provides | |
1162 the contents of the file as one or more strings. | |
1163 | |
1164 {% highlight dart %} | |
1165 #import('dart:io'); | |
1166 | |
1167 main() { | |
1168 var config = new File('config.txt'); | |
1169 | |
1170 // Put the whole file in a single string. | |
1171 config.readAsText(Encoding.UTF_8).then((String contents) { | |
1172 print("The entire file is ${contents.length} characters long"); | |
1173 }); | |
1174 | |
1175 // Put each line of the file into its own string. | |
1176 config.readAsLines(Encoding.UTF_8).then((List<String> lines) { | |
1177 print("The entire file is ${lines.length} lines long"); | |
1178 }); | |
1179 } | |
1180 {% endhighlight %} | |
1181 | |
1182 #### Reading a file as binary | |
1183 | |
1184 The following code reads an entire file into a list of bytes (as ints). | |
1185 | |
1186 {% highlight dart %} | |
1187 #import('dart:io'); | |
1188 | |
1189 main() { | |
1190 var config = new File('config.txt'); | |
1191 | |
1192 config.readAsBytes().then((List<int> contents) { | |
1193 print("The entire file is ${contents.length} bytes long"); | |
1194 }); | |
1195 } | |
1196 {% endhighlight %} | |
1197 | |
1198 In the examples above, the API uses Future objects to signal completion. | |
1199 This asynchronous technique is preferred for performance reasons. | |
1200 However, you have the option to use synchronous and blocking | |
1201 methods: `readAsTextSync()`, `readAsLinesSync()`, and `readAsBytesSync()`. | |
1202 | |
1203 #### Handling errors | |
1204 | |
1205 Errors are thrown as exceptions if you do not | |
1206 register an explicit handler. If you want to | |
1207 capture an error, you can register a handleException handler | |
1208 with the Future object. | |
1209 | |
1210 {% highlight dart %} | |
1211 #import('dart:io'); | |
1212 | |
1213 main() { | |
1214 var config = new File('config.txt'); | |
1215 Future<String> readFile = config.readAsText(); | |
1216 readFile.handleException((e) { | |
1217 print('Error: $e'); | |
1218 // ... other error handling goes here ... | |
1219 return true; // We've handled the exception; no need to propagate it. | |
1220 }); | |
1221 | |
1222 readFile.then((text) => print(text)); | |
1223 } | |
1224 {% endhighlight %} | |
1225 | |
1226 #### Streaming file contents | |
1227 | |
1228 Use an [InputStream](http://api.dartlang.org/io/InputStream.html) | |
1229 to read a file, a little at a time. The `onData` | |
1230 callback runs when data | |
1231 is ready to be read. When the InputStream | |
1232 is finished reading the file, the `onClosed` callback executes. | |
1233 | |
1234 {% highlight dart %} | |
1235 #import('dart:io'); | |
1236 | |
1237 main() { | |
1238 var config = new File('config.txt'); | |
1239 var inputStream = config.openInputStream(); | |
1240 | |
1241 inputStream.onError = (e) => print(e); | |
1242 inputStream.onClosed = () => print("file is now closed"); | |
1243 inputStream.onData = () { | |
1244 List<int> bytes = inputStream.read(); | |
1245 print("Read ${bytes.length} bytes from stream"); | |
1246 }; | |
1247 } | |
1248 {% endhighlight %} | |
1249 | |
1250 #### Writing file contents | |
1251 | |
1252 Use an [OutputStream](http://api.dartlang.org/io/OutputStream.html) | |
1253 to write data to a file. Open a file | |
1254 for writing with `openOutputStream()` and declare a | |
1255 mode. Use `FileMode.WRITE` to completely overwrite existing data in the file, | |
1256 and `FileMode.APPEND` | |
1257 to add to the end. | |
1258 | |
1259 {% highlight dart %} | |
1260 #import('dart:io'); | |
1261 | |
1262 main() { | |
1263 var logFile = new File('log.txt'); | |
1264 var out = logFile.openOutputStream(FileMode.WRITE); | |
1265 out.writeString('FILE ACCESSED ${new Date.now()}'); | |
1266 out.close(); | |
1267 } | |
1268 {% endhighlight %} | |
1269 | |
1270 To write binary data, use `write(List<int> buffer)`. | |
1271 | |
1272 #### Listing files in a directory | |
1273 | |
1274 Finding all files and subdirectories for a directory is an asynchronous | |
1275 operation. The `list()` method returns a | |
1276 [DirectoryLister](http://api.dartlang.org/io/DirectoryLister.html), | |
1277 on which you can register callback handlers to be notified when | |
1278 a file is encountered (using `onFile`) or when a directory is | |
1279 encountered (using `onDir`). | |
1280 | |
1281 {% highlight dart %} | |
1282 #import('dart:io'); | |
1283 | |
1284 main() { | |
1285 var dir = new Directory('/tmp'); | |
1286 | |
1287 DirectoryLister lister = dir.list(recursive:true); //returns immediately | |
1288 lister.onError = (e) => print(e); | |
1289 lister.onFile = (name) => print("Found file $name"); | |
1290 lister.onDir = (name) => print("Found dir $name"); | |
1291 } | |
1292 {% endhighlight %} | |
1293 | |
1294 No equivalent synchronous API exists for walking a directory | |
1295 tree. | |
1296 | |
1297 | |
1298 #### Other common functionality | |
1299 | |
1300 The File and Directory interfaces contain other functionality, | |
1301 including but not limited to: | |
1302 | |
1303 * [creating a file](http://api.dartlang.org/io/File.html#create) | |
1304 * [creating a directory](http://api.dartlang.org/io/Directory.html#create) | |
1305 * [deleting a file](http://api.dartlang.org/io/File.html#delete) | |
1306 * [deleting a directory](http://api.dartlang.org/io/Directory.html#delete) | |
1307 * [getting the length of a file](http://api.dartlang.org/io/File.html#length) | |
1308 * [random access to a file](http://api.dartlang.org/io/File.html#open) | |
1309 | |
1310 #### More information | |
1311 | |
1312 Refer to the full API docs for | |
1313 [File](http://api.dartlang.org/io/File.html), | |
1314 [Directory](http://api.dartlang.org/io/Directory.html), | |
1315 and [DirectoryLister](http://api.dartlang.org/io/DirectoryLister.html) | |
1316 for a full list of methods. For more information, | |
1317 read [An introduction to the dart:io library](/articles/io/). | |
1318 | |
1319 [Back to contents.](#toc) | |
1320 {:.up-to-toc} | |
1321 | |
1322 | |
1323 {% comment %} | |
1324 ### Sockets | |
1325 | |
1326 Coming soon. | |
1327 | |
1328 ### HTTP server and client | |
1329 | |
1330 Coming soon. | |
1331 | |
1332 ### Web socket server | |
1333 | |
1334 Coming soon. | |
1335 {% endcomment %} | |
1336 | |
1337 | |
1338 ## dart:json - Encoding and decoding objects {#json} | |
1339 | |
1340 [JSON](http://www.json.org/) is a simple text | |
1341 format for representing structured objects and collections. | |
1342 The [JSON library](http://api.dartlang.org/json.html) | |
1343 decodes JSON-formatted strings into Dart objects, | |
1344 and encodes objects into JSON-formatted strings. | |
1345 | |
1346 The Dart JSON library works in both web apps and command-line apps. | |
1347 | |
1348 ### Importing the JSON library | |
1349 | |
1350 To use the JSON library, import dart:json. | |
1351 | |
1352 {% highlight dart %} | |
1353 #import('dart:json'); | |
1354 | |
1355 main() { | |
1356 // The app | |
1357 } | |
1358 {% endhighlight %} | |
1359 | |
1360 ### Decoding JSON | |
1361 | |
1362 Decode a JSON-encoded string into a Dart object with `JSON.parse()`. | |
1363 | |
1364 {% highlight dart %} | |
1365 #import('dart:json'); | |
1366 | |
1367 main() { | |
1368 // NOTE: Be sure to use ", not ', inside the JSON string. | |
1369 var jsonString = ''' | |
1370 [ | |
1371 {"score": 40}, | |
1372 {"score": 80} | |
1373 ] | |
1374 '''; | |
1375 | |
1376 var scores = JSON.parse(jsonString); | |
1377 assert(scores is List); | |
1378 | |
1379 var firstScore = scores[0]; | |
1380 assert(firstScore is Map); | |
1381 assert(firstScore['score'] == 40); | |
1382 } | |
1383 {% endhighlight %} | |
1384 | |
1385 ### Encoding JSON | |
1386 | |
1387 Encode a supported Dart object into a JSON-formatted string | |
1388 with `JSON.stringify()`. | |
1389 | |
1390 Only objects of type List, Map, String, int, double, bool, or null can | |
1391 be encoded into JSON. | |
1392 List and Map objects are encoded recursively. | |
1393 | |
1394 {% highlight dart %} | |
1395 #import('dart:json'); | |
1396 | |
1397 main() { | |
1398 var scores = [ | |
1399 {'score': 40}, | |
1400 {'score': 80}, | |
1401 {'score': 100, 'overtime': true, 'special_guest': null} | |
1402 ]; | |
1403 | |
1404 var jsonText = JSON.stringify(scores); | |
1405 assert(jsonText == '[{"score":40},{"score":80},' | |
1406 '{"score":100,"overtime":true,' | |
1407 '"special_guest":null}]'); | |
1408 } | |
1409 {% endhighlight %} | |
1410 | |
1411 [Back to contents.](#toc) | |
1412 {:.up-to-toc} | |
1413 | |
1414 ## dart:uri - Manipulating URLs {#uri} | |
1415 | |
1416 The [URI library](http://api.dartlang.org/uri.html) provides functions | |
1417 to encode and decode strings for use in URIs. These functions | |
1418 handle characters that are special for URIs, such as `&` and `=`. | |
1419 | |
1420 The URI library also contains the | |
1421 [Uri class](http://api.dartlang.org/uri/Uri.html), | |
1422 which parses and exposes | |
1423 the components of a URI, such as domain, port, and scheme. | |
1424 | |
1425 The URI library works in both web apps and command-line apps. | |
1426 | |
1427 ### Importing the URI library | |
1428 | |
1429 To use the URI library, import dart:uri. | |
1430 | |
1431 {% highlight dart %} | |
1432 #import('dart:uri'); | |
1433 | |
1434 main() { | |
1435 // The app | |
1436 } | |
1437 {% endhighlight %} | |
1438 | |
1439 ### Encoding and decoding fully qualified URIs | |
1440 | |
1441 To encode and decode characters *except* those with special meaning in a URI | |
1442 (such as `/`, `:`, `&`, `#`), use | |
1443 [encodeUri()](http://api.dartlang.org/uri.html#encodeUri) | |
1444 and [decodeUri()](http://api.dartlang.org/uri.html#decodeUri). Use these | |
1445 functions when you need to encode or decode a fully qualified URI, | |
1446 leaving intact special URI characters. | |
1447 | |
1448 {% highlight dart %} | |
1449 #import('dart:uri'); | |
1450 | |
1451 main() { | |
1452 var uri = 'http://example.org/api?foo=some message'; | |
1453 var encoded = encodeUri(uri); | |
1454 assert(encoded == 'http://example.org/api?foo=some%20message'); | |
1455 | |
1456 var decoded = decodeUri(encoded); | |
1457 assert(uri == decoded); | |
1458 } | |
1459 {% endhighlight %} | |
1460 | |
1461 Notice how only the space between `some` and `message` was encoded. | |
1462 | |
1463 ### Encoding and decoding URI components | |
1464 | |
1465 To encode and decode all characters in a string that have special meaning | |
1466 in a URI, including (but not limited to) | |
1467 `/`, `&`, and `:`, use | |
1468 [encodeUriComponent()](http://api.dartlang.org/uri.html#encodeUriComponent) and | |
1469 [decodeUriComponent()](http://api.dartlang.org/uri.html#decodeUriComponent). | |
1470 | |
1471 {% highlight dart %} | |
1472 #import('dart:uri'); | |
1473 | |
1474 main() { | |
1475 var uri = 'http://example.org/api?foo=some message'; | |
1476 var encoded = encodeUriComponent(uri); | |
1477 assert(encoded == 'http%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message'); | |
1478 | |
1479 var decoded = decodeUriComponent(encoded); | |
1480 assert(uri == decoded); | |
1481 } | |
1482 {% endhighlight %} | |
1483 | |
1484 Notice how every special character was encoded. For example, `/` was encoded | |
1485 to `%2F`. | |
1486 | |
1487 ### Parsing URIs | |
1488 | |
1489 You can parse a URI into its parts with the | |
1490 [Uri.fromString() constructor](http://api.dartlang.org/uri/Uri.html#Uri). | |
1491 | |
1492 {% highlight dart %} | |
1493 #import('dart:uri'); | |
1494 | |
1495 main() { | |
1496 var uri = new Uri.fromString('http://example.org/foo/bar#frag'); | |
1497 | |
1498 assert(uri.scheme == 'http'); | |
1499 assert(uri.domain == 'example.org'); | |
1500 assert(uri.path == '/foo/bar'); | |
1501 assert(uri.fragment == 'frag'); | |
1502 } | |
1503 {% endhighlight %} | |
1504 | |
1505 The Uri class exposes more URI components. Learn more by | |
1506 reading the [Uri API docs](http://api.dartlang.org/uri/Uri.html). | |
1507 | |
1508 ### Building URIs | |
1509 | |
1510 You can build up a URI from individual parts using the | |
1511 [Uri() constructor](http://api.dartlang.org/uri/Uri.html#Uri). | |
1512 | |
1513 {% highlight dart %} | |
1514 #import('dart:uri'); | |
1515 | |
1516 main() { | |
1517 var uri = new Uri(scheme: 'http', domain: 'example.org', path: '/foo/bar', | |
1518 fragment: 'frag'); | |
1519 assert(uri.toString() == 'http://example.org/foo/bar#frag'); | |
1520 } | |
1521 {% endhighlight %} | |
1522 | |
1523 [Back to contents.](#toc) | |
1524 {:.up-to-toc} | |
1525 | |
1526 | |
1527 ## dart:utf - Strings and Unicode {#utf} | |
1528 | |
1529 The [UTF library](http://api.dartlang.org/utf.html) helps bridge the gap | |
1530 between strings and UTF8/UTF16/UTF32 encodings. | |
1531 | |
1532 ### Importing the UTF library | |
1533 | |
1534 To use the UTF library, import dart:utf. | |
1535 | |
1536 {% highlight dart %} | |
1537 #import('dart:utf'); | |
1538 | |
1539 main() { | |
1540 // The app | |
1541 } | |
1542 {% endhighlight %} | |
1543 | |
1544 ### Decoding UTF8 characters | |
1545 | |
1546 Use `decodeUtf8()` to decode UTF8-encoded bytes to a Dart string. | |
1547 | |
1548 {% highlight dart %} | |
1549 #import('dart:utf'); | |
1550 | |
1551 main() { | |
1552 var string = decodeUtf8([0xc3, 0x8e, 0xc3, 0xb1, 0xc5, 0xa3, 0xc3, 0xa9, | |
1553 0x72, 0xc3, 0xb1, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, | |
1554 0xae, 0xc3, 0xb6, 0xc3, 0xb1, 0xc3, 0xa5, 0xc4, | |
1555 0xbc, 0xc3, 0xae, 0xc5, 0xbe, 0xc3, 0xa5, 0xc5, | |
1556 0xa3, 0xc3, 0xae, 0xe1, 0xbb, 0x9d, 0xc3, 0xb1]); | |
1557 assert(string == "Îñţérñåţîöñåļîžåţîờñ"); | |
1558 } | |
1559 {% endhighlight %} | |
1560 | |
1561 ### Encoding strings to UTF8 bytes | |
1562 | |
1563 Use `encodeUtf8()` to encode a Dart string as a list of UTF8-encoded bytes. | |
1564 | |
1565 {% highlight dart %} | |
1566 #import('dart:utf'); | |
1567 | |
1568 main() { | |
1569 List<int> expected = [0xc3, 0x8e, 0xc3, 0xb1, 0xc5, 0xa3, 0xc3, 0xa9, 0x72, | |
1570 0xc3, 0xb1, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xc3, | |
1571 0xb6, 0xc3, 0xb1, 0xc3, 0xa5, 0xc4, 0xbc, 0xc3, 0xae, | |
1572 0xc5, 0xbe, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xe1, | |
1573 0xbb, 0x9d, 0xc3, 0xb1]; | |
1574 | |
1575 List<int> encoded = encodeUtf8("Îñţérñåţîöñåļîžåţîờñ"); | |
1576 | |
1577 assert(() { | |
1578 if (encoded.length != expected.length) return false; | |
1579 for (var i = 0; i < encoded.length; i++) { | |
1580 if (encoded[i] != expected[i]) return false; | |
1581 } | |
1582 return true; | |
1583 }); | |
1584 } | |
1585 {% endhighlight %} | |
1586 | |
1587 ### Other functionality | |
1588 | |
1589 The UTF library can decode and encode UTF16 and UTF32 bytes. | |
1590 The library can also convert directly to and from Unicode codepoints | |
1591 and UTF8-encoded bytes. Learn more about the | |
1592 [UTF library](http://api.dartlang.org/utf.html). | |
1593 | |
1594 [Back to contents.](#toc) | |
1595 {:.up-to-toc} | |
1596 | |
1597 | |
1598 ## dart:crypto - Hash codes and more {#crypto} | |
1599 | |
1600 The [Dart crypto library](http://api.dartlang.org/crypto.html) | |
1601 contains functions useful for cryptographic applications, | |
1602 such as creating cryptographic hashes and generating | |
1603 has-based message authentication codes. | |
1604 | |
1605 ### Importing the crypto library | |
1606 | |
1607 To use the crypto library, import dart:crypto. | |
1608 | |
1609 {% highlight dart %} | |
1610 #import('dart:crypto'); | |
1611 | |
1612 main() { | |
1613 // The app | |
1614 } | |
1615 {% endhighlight %} | |
1616 | |
1617 ### Generating cryptographic hashes | |
1618 | |
1619 You can generate [SHA256](http://api.dartlang.org/crypto/SHA256.html), | |
1620 [SHA1](http://api.dartlang.org/crypto/SHA1.html), and | |
1621 [MD5](http://api.dartlang.org/crypto/MD5.html) hashes | |
1622 (also known as *digests* or *message digests*) | |
1623 with dart:crypto. We | |
1624 recommend using SHA256, but we have included SHA1 and MD5 for | |
1625 compatibility with older systems. | |
1626 | |
1627 Learn more about | |
1628 [cryptographic hash functions](http://en.wikipedia.org/wiki/Cryptographic_hash_f
unction). | |
1629 | |
1630 {% highlight dart %} | |
1631 #import('dart:crypto'); | |
1632 | |
1633 main() { | |
1634 var sha256 = new SHA256(); | |
1635 var digest = sha256.update("message".charCodes()).digest(); | |
1636 var hexString = CryptoUtils.bytesToHex(digest); | |
1637 assert(hexString == | |
1638 'ab530a13e45914982b79f9b7e3fba994cfd1f3fb22f71cea1afbf02b460c6d1d'); | |
1639 } | |
1640 {% endhighlight %} | |
1641 | |
1642 If the message content changes, the digest value also changes | |
1643 (with a very high probability). | |
1644 | |
1645 ### Generating message authentication codes | |
1646 | |
1647 Use a hash-based message authentication code (HMAC) to combine a | |
1648 cryptographic hash function with a secret key. | |
1649 Learn more about [HMACs](http://en.wikipedia.org/wiki/HMAC). | |
1650 | |
1651 {% highlight dart %} | |
1652 #import('dart:crypto'); | |
1653 main() { | |
1654 var hmac = new HMAC(new SHA256(), "secretkey".charCodes()); | |
1655 var hmacDigest = hmac.update("message".charCodes()).digest(); | |
1656 var hmacHex = CryptoUtils.bytesToHex(hmacDigest); | |
1657 assert(hmacHex == | |
1658 '5c3e2f56de9411068f675ef32ffa12735210b9cbfee2ba521367a3955334a343'); | |
1659 } | |
1660 {% endhighlight %} | |
1661 | |
1662 If either the message contents or key changes, | |
1663 the digest value also changes (with a very high probability). | |
1664 | |
1665 ### Generating Base64 strings | |
1666 | |
1667 You can represent binary data as a character string by using the | |
1668 [Base64](http://en.wikipedia.org/wiki/Base_64) encoding scheme. Use the | |
1669 `CryptoUtils.bytesToBase64()` utility method to convert a list | |
1670 of bytes into a base64-encoded string. | |
1671 | |
1672 {% highlight dart %} | |
1673 #import('dart:crypto'); | |
1674 #import('dart:io'); | |
1675 | |
1676 main() { | |
1677 var file = new File('icon.ico'); | |
1678 var bytes = file.readAsBytesSync(); | |
1679 var base64 = CryptoUtils.bytesToBase64(bytes); | |
1680 assert(base64 == | |
1681 "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38G" | |
1682 "IAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="); | |
1683 } | |
1684 {% endhighlight %} | |
1685 | |
1686 [Back to contents.](#toc) | |
1687 {:.up-to-toc} | |
1688 | |
1689 | |
OLD | NEW |