Contents

A tour of the core libraries

此页面显示了如何使用Dart核心库中的主要功能. 这只是一个概述,绝不是全面的. 每当需要有关类的更多详细信息时,请查阅Dart API参考.

dart:core
内置类型,集合和其他核心功能. 该库自动导入到每个Dart程序中.
dart:async
支持诸如Future和Stream之类的异步编程.
dart:math
数学常数和函数,以及一个随机数生成器.
dart:convert
编码器和解码器,用于在不同的数据表示形式(包括JSON和UTF-8)之间进行转换.
dart:html
DOM和其他基于浏览器的应用程序的API.
dart:io
可使用Dart VM的程序的I / O,包括Flutter应用程序,服务器和命令行脚本.

此页面仅是概述. 它仅涵盖少数dart:*库,而没有第三方库.

Other places to find library information are the pub.dev site and the Dart web developer library guide. You can find API documentation for all dart:* libraries in the Dart API reference or, if you’re using Flutter, the Flutter API reference.

dart:core - numbers, collections, strings, and more

dart:core库( API参考 )提供了一套很小但很关键的内置功能. 该库自动导入到每个Dart程序中.

Printing to the console

顶级print()方法采用单个参数(任何Object),并在控制台中显示该对象的字符串值(由toString()返回).

print(anObject);
print('I drink $tea.');

有关基本字符串和toString()更多信息,请参阅语言导览中的字符串 .

Numbers

dart:core库定义了num,int和double类,它们具有一些用于处理数字的基本实用程序.

您可以分别使用int和double的parse()方法将字符串转换为整数或double:

assert(int.parse('42') == 42);
assert(int.parse('0x42') == 66);
assert(double.parse('0.50') == 0.5);

或使用num的parse()方法,该方法会在可能的情况下创建一个整数,否则将创建一个double:

assert(num.parse('42') is int);
assert(num.parse('0x42') is int);
assert(num.parse('0.50') is double);

要指定整数的底数,请添加一个radix参数:

assert(int.parse('42', radix: 16) == 66);

使用toString()方法将int或double转换为字符串. 要指定小数点右边的位数,请使用toStringAsFixed(). 要指定字符串中的有效位数,请使用toStringAsPrecision():

// Convert an int to a string.
assert(42.toString() == '42');

// Convert a double to a string.
assert(123.456.toString() == '123.456');

// Specify the number of digits after the decimal.
assert(123.456.toStringAsFixed(2) == '123.46');

// Specify the number of significant figures.
assert(123.456.toStringAsPrecision(2) == '1.2e+2');
assert(double.parse('1.2e+2') == 120.0);

有关更多信息,请参见int, doublenum的API文档. 另请参见dart:math部分 .

Strings and regular expressions

A string in Dart is an immutable sequence of UTF-16 code units. The language tour has more information about strings. You can use regular expressions (RegExp objects) to search within strings and to replace parts of strings.

String类将以下方法定义为split()contains()startsWith()endsWith()等.

Searching inside a string

您可以找到字符串中的特定位置,以及检查字符串是以特定模式开始还是以特定模式结束. 例如:

// Check whether a string contains another string.
assert('Never odd or even'.contains('odd'));

// Does a string start with another string?
assert('Never odd or even'.startsWith('Never'));

// Does a string end with another string?
assert('Never odd or even'.endsWith('even'));

// Find the location of a string inside a string.
assert('Never odd or even'.indexOf('odd') == 6);

Extracting data from a string

您可以从字符串中分别获取单个字符作为Strings或ints. 确切地说,您实际上获得了单独的UTF-16代码单元. 高号字符(例如高音谱号符号('\ u {1D11E}'))每个都是两个代码单元.

您还可以提取子字符串或将字符串拆分为子字符串列表:

// Grab a substring.
assert('Never odd or even'.substring(6, 9) == 'odd');

// Split a string using a string pattern.
var parts = 'structured web apps'.split(' ');
assert(parts.length == 3);
assert(parts[0] == 'structured');

// Get a UTF-16 code unit (as a string) by index.
assert('Never odd or even'[0] == 'N');

// Use split() with an empty string parameter to get
// a list of all characters (as Strings); good for
// iterating.
for (var char in 'hello'.split('')) {
  print(char);
}

// Get all the UTF-16 code units in the string.
var codeUnitList =
    'Never odd or even'.codeUnits.toList();
assert(codeUnitList[0] == 78);

Converting to uppercase or lowercase

您可以轻松地将字符串转换为它们的大写和小写形式:

// Convert to uppercase.
assert('structured web apps'.toUpperCase() ==
    'STRUCTURED WEB APPS');

// Convert to lowercase.
assert('STRUCTURED WEB APPS'.toLowerCase() ==
    'structured web apps');

Trimming and empty strings

使用trim()删除所有前导和尾随空白. 要检查字符串是否为空(长度为零),请使用isEmpty .

// Trim a string.
assert('  hello  '.trim() == 'hello');

// Check whether a string is empty.
assert(''.isEmpty);

// Strings with only white space are not empty.
assert('  '.isNotEmpty);

Replacing part of a string

字符串是不可变的对象,这意味着您可以创建它们,但不能更改它们. 如果仔细查看String API参考,您会注意到,没有任何一种方法实际更改String的状态. 例如,方法replaceAll()返回一个新的String而不更改原始的String:

var greetingTemplate = 'Hello, NAME!';
var greeting =
    greetingTemplate.replaceAll(RegExp('NAME'), 'Bob');

// greetingTemplate didn't change.
assert(greeting != greetingTemplate);

Building a string

要以编程方式生成字符串,可以使用StringBuffer. 在调用toString()之前,StringBuffer不会生成新的String对象. writeAll()方法有一个可选的第二个参数,可让您指定分隔符,在本例中为空格.

var sb = StringBuffer();
sb
  ..write('Use a StringBuffer for ')
  ..writeAll(['efficient', 'string', 'creation'], ' ')
  ..write('.');

var fullString = sb.toString();

assert(fullString ==
    'Use a StringBuffer for efficient string creation.');

Regular expressions

RegExp类提供与JavaScript正则表达式相同的功能. 使用正则表达式进行有效的字符串搜索和模式匹配.

// Here's a regular expression for one or more digits.
var numbers = RegExp(r'\d+');

var allCharacters = 'llamas live fifteen to twenty years';
var someDigits = 'llamas live 15 to 20 years';

// contains() can use a regular expression.
assert(!allCharacters.contains(numbers));
assert(someDigits.contains(numbers));

// Replace every match with another string.
var exedOut = someDigits.replaceAll(numbers, 'XX');
assert(exedOut == 'llamas live XX to XX years');

您也可以直接使用RegExp类. Match类提供对正则表达式匹配的访问.

var numbers = RegExp(r'\d+');
var someDigits = 'llamas live 15 to 20 years';

// Check whether the reg exp has a match in a string.
assert(numbers.hasMatch(someDigits));

// Loop through all matches.
for (var match in numbers.allMatches(someDigits)) {
  print(match.group(0)); // 15, then 20
}

More information

有关方法的完整列表,请参考String API参考 . 另请参阅有关StringBuffer, Pattern, RegExpMatch的API参考.

Collections

Dart附带了一个核心collections API,其中包括列表,集合和地图的类.

Lists

如语言之旅所示,您可以使用文字来创建和初始化list . 或者,使用List构造函数之一. List类还定义了几种向列表中添加项目或从列表中删除项目的方法.

// Use a List constructor.
var vegetables = List();

// Or simply use a list literal.
var fruits = ['apples', 'oranges'];

// Add to a list.
fruits.add('kiwis');

// Add multiple items to a list.
fruits.addAll(['grapes', 'bananas']);

// Get the list length.
assert(fruits.length == 5);

// Remove a single item.
var appleIndex = fruits.indexOf('apples');
fruits.removeAt(appleIndex);
assert(fruits.length == 4);

// Remove all elements from a list.
fruits.clear();
assert(fruits.isEmpty);

使用indexOf()查找列表中对象的索引:

var fruits = ['apples', 'oranges'];

// Access a list item by index.
assert(fruits[0] == 'apples');

// Find an item in a list.
assert(fruits.indexOf('apples') == 0);

使用sort()方法sort()列表进行sort() . 您可以提供比较两个对象的排序功能. 此排序函数必须返回<0表示较小的值 ,0表示相同的值 ,> 0表示较大的值 . 以下示例使用compareTo() ,它由Comparable定义并由String实现.

var fruits = ['bananas', 'apples', 'oranges'];

// Sort a list.
fruits.sort((a, b) => a.compareTo(b));
assert(fruits[0] == 'apples');

列表是参数化类型,因此您可以指定列表应包含的类型:

// This list should contain only strings.
var fruits = List<String>();

fruits.add('apples');
var fruit = fruits[0];
assert(fruit is String);
fruits.add(5); // Error: 'int' can't be assigned to 'String'

有关方法的完整列表,请参考List API参考 .

Sets

Dart中的集合是无序的唯一项集合. 由于集合是无序的,因此无法通过索引(位置)获得集合的项目.

var ingredients = Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);
assert(ingredients.length == 3);

// Adding a duplicate item has no effect.
ingredients.add('gold');
assert(ingredients.length == 3);

// Remove an item from a set.
ingredients.remove('gold');
assert(ingredients.length == 2);

使用contains()containsAll()来检查一个或多个对象是否在集合中:

var ingredients = Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);

// Check whether an item is in the set.
assert(ingredients.contains('titanium'));

// Check whether all the items are in the set.
assert(ingredients.containsAll(['titanium', 'xenon']));

相交是一个集合,其项位于其他两个集合中.

var ingredients = Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);

// Create the intersection of two sets.
var nobleGases = Set.from(['xenon', 'argon']);
var intersection = ingredients.intersection(nobleGases);
assert(intersection.length == 1);
assert(intersection.contains('xenon'));

有关方法的完整列表,请参考Set API参考 .

Maps

映射通常称为字典哈希 ,是键-值对的无序集合. 地图将键与某个值相关联,以便于检索. 与JavaScript不同,Dart对象不是地图.

您可以使用简洁的文字语法声明地图,也可以使用传统的构造函数:

// Maps often use strings as keys.
var hawaiianBeaches = {
  'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
  'Big Island': ['Wailea Bay', 'Pololu Beach'],
  'Kauai': ['Hanalei', 'Poipu']
};

// Maps can be built from a constructor.
var searchTerms = Map();

// Maps are parameterized types; you can specify what
// types the key and value should be.
var nobleGases = Map<int, String>();

您可以使用方括号语法添加,获取和设置地图项. 使用remove()从映射中删除键及其值.

var nobleGases = {54: 'xenon'};

// Retrieve a value with a key.
assert(nobleGases[54] == 'xenon');

// Check whether a map contains a key.
assert(nobleGases.containsKey(54));

// Remove a key and its value.
nobleGases.remove(54);
assert(!nobleGases.containsKey(54));

您可以从地图中检索所有值或所有键:

var hawaiianBeaches = {
  'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
  'Big Island': ['Wailea Bay', 'Pololu Beach'],
  'Kauai': ['Hanalei', 'Poipu']
};

// Get all the keys as an unordered collection
// (an Iterable).
var keys = hawaiianBeaches.keys;

assert(keys.length == 3);
assert(Set.from(keys).contains('Oahu'));

// Get all the values as an unordered collection
// (an Iterable of Lists).
var values = hawaiianBeaches.values;
assert(values.length == 3);
assert(values.any((v) => v.contains('Waikiki')));

要检查地图是否包含键,请使用containsKey() . 因为映射值可以为null,所以您不能仅仅依靠获取键的值并检查null来确定键的存在.

var hawaiianBeaches = {
  'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
  'Big Island': ['Wailea Bay', 'Pololu Beach'],
  'Kauai': ['Hanalei', 'Poipu']
};

assert(hawaiianBeaches.containsKey('Oahu'));
assert(!hawaiianBeaches.containsKey('Florida'));

当且仅当映射中不存在该键时,才想为该键分配值时,请使用putIfAbsent()方法. 您必须提供一个返回值的函数.

var teamAssignments = {};
teamAssignments.putIfAbsent(
    'Catcher', () => pickToughestKid());
assert(teamAssignments['Catcher'] != null);

有关方法的完整列表,请参考Map API参考 .

Common collection methods

列表,设置和地图共享许多集合中常见的功能. List和Set实现的Iterable类定义了一些常用功能.

使用isEmptyisNotEmpty检查列表,集合或映射是否具有项:

var coffees = [];
var teas = ['green', 'black', 'chamomile', 'earl grey'];
assert(coffees.isEmpty);
assert(teas.isNotEmpty);

要将功能应用于列表,集合或映射中的每个项目,可以使用forEach()

var teas = ['green', 'black', 'chamomile', 'earl grey'];

teas.forEach((tea) => print('I drink $tea'));

在地图上调用forEach()时,您的函数必须采用两个参数(键和值):

hawaiianBeaches.forEach((k, v) {
  print('I want to visit $k and swim at $v');
  // I want to visit Oahu and swim at
  // [Waikiki, Kailua, Waimanalo], etc.
});

Iterables提供map()方法,该方法在单个对象中为您提供所有结果:

var teas = ['green', 'black', 'chamomile', 'earl grey'];

var loudTeas = teas.map((tea) => tea.toUpperCase());
loudTeas.forEach(print);

要强制在每个项目上立即调用您的函数,请使用map().toList()map().toSet()

var loudTeas =
    teas.map((tea) => tea.toUpperCase()).toList();

使用Iterable的where()方法获取与条件匹配的所有项目. 使用Iterable的any()every()方法检查部分或全部项目是否符合条件.

var teas = ['green', 'black', 'chamomile', 'earl grey'];

// Chamomile is not caffeinated.
bool isDecaffeinated(String teaName) =>
    teaName == 'chamomile';

// Use where() to find only the items that return true
// from the provided function.
var decaffeinatedTeas =
    teas.where((tea) => isDecaffeinated(tea));
// or teas.where(isDecaffeinated)

// Use any() to check whether at least one item in the
// collection satisfies a condition.
assert(teas.any(isDecaffeinated));

// Use every() to check whether all the items in a
// collection satisfy a condition.
assert(!teas.every(isDecaffeinated));

有关方法的完整列表,请参考Iterable API参考以及List, SetMap的参考.

URIs

The Uri class provides functions to encode and decode strings for use in URIs (which you might know as URLs). These functions handle characters that are special for URIs, such as & and =. The Uri class also parses and exposes the components of a URI—host, port, scheme, and so on.

Encoding and decoding fully qualified URIs

进行编码和解码的字符除了那些在URI特殊含义(如/:&# ),使用encodeFull()decodeFull()方法. 这些方法非常适合编码或解码完全限定的URI,而保留完整的特殊URI字符.

var uri = 'https://example.org/api?foo=some message';

var encoded = Uri.encodeFull(uri);
assert(encoded ==
    'https://example.org/api?foo=some%20message');

var decoded = Uri.decodeFull(encoded);
assert(uri == decoded);

公告之间的空间怎么只有somemessage进行编码.

Encoding and decoding URI components

要对URI中具有特殊含义的所有字符串字符进行编码和解码,包括(但不限于) /&: ,请使用encodeComponent()decodeComponent()方法.

var uri = 'https://example.org/api?foo=some message';

var encoded = Uri.encodeComponent(uri);
assert(encoded ==
    'https%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message');

var decoded = Uri.decodeComponent(encoded);
assert(uri == decoded);

注意每个特殊字符是如何编码的. 例如, /被编码为/ .

Parsing URIs

如果您有Uri对象或URI字符串,则可以使用Uri字段(例如path来获取其一部分. 要从字符串创建Uri,请使用parse()静态方法:

var uri =
    Uri.parse('https://example.org:8080/foo/bar#frag');

assert(uri.scheme == 'https');
assert(uri.host == 'example.org');
assert(uri.path == '/foo/bar');
assert(uri.fragment == 'frag');
assert(uri.origin == 'https://example.org:8080');

有关可以获取的更多URI组件,请参见Uri API参考 .

Building URIs

您可以使用Uri()构造函数从各个部分构建URI:

var uri = Uri(
    scheme: 'https',
    host: 'example.org',
    path: '/foo/bar',
    fragment: 'frag');
assert(
    uri.toString() == 'https://example.org/foo/bar#frag');

Dates and times

DateTime对象是一个时间点. 时区可以是UTC或本地时区.

您可以使用几种构造函数创建DateTime对象:

// Get the current date and time.
var now = DateTime.now();

// Create a new DateTime with the local time zone.
var y2k = DateTime(2000); // January 1, 2000

// Specify the month and day.
y2k = DateTime(2000, 1, 2); // January 2, 2000

// Specify the date as a UTC time.
y2k = DateTime.utc(2000); // 1/1/2000, UTC

// Specify a date and time in ms since the Unix epoch.
y2k = DateTime.fromMillisecondsSinceEpoch(946684800000,
    isUtc: true);

// Parse an ISO 8601 date.
y2k = DateTime.parse('2000-01-01T00:00:00Z');

日期的millisecondsSinceEpoch属性返回自" Unix纪元"(1970年1月1日,UTC)以来的毫秒数:

// 1/1/2000, UTC
var y2k = DateTime.utc(2000);
assert(y2k.millisecondsSinceEpoch == 946684800000);

// 1/1/1970, UTC
var unixEpoch = DateTime.utc(1970);
assert(unixEpoch.millisecondsSinceEpoch == 0);

使用Duration类来计算两个日期之间的差,并向前或向后移动日期:

var y2k = DateTime.utc(2000);

// Add one year.
var y2001 = y2k.add(Duration(days: 366));
assert(y2001.year == 2001);

// Subtract 30 days.
var december2000 = y2001.subtract(Duration(days: 30));
assert(december2000.year == 2000);
assert(december2000.month == 12);

// Calculate the difference between two dates.
// Returns a Duration object.
var duration = y2001.difference(y2k);
assert(duration.inDays == 366); // y2k was a leap year.

有关方法的完整列表,请参阅API参考中有关DateTimeDuration的信息.

Utility classes

核心库包含各种实用程序类,可用于排序,映射值和迭代.

Comparing objects

实现Comparable接口,以指示可以将一个对象与另一个对象进行比较,通常用于排序. 所述compareTo()方法返回<0 较小 ,0为相同的 ,并且> 0为 .

class Line implements Comparable<Line> {
  final int length;
  const Line(this.length);

  @override
  int compareTo(Line other) => length - other.length;
}

void main() {
  var short = const Line(1);
  var long = const Line(100);
  assert(short.compareTo(long) < 0);
}

Implementing map keys

Dart中的每个对象都会自动提供一个整数哈希码,因此可以用作地图中的键. 但是,您可以覆盖hashCode getter以生成自定义哈希码. 如果这样做,您可能还想覆盖==运算符. 相等的对象(通过== )必须具有相同的哈希码. 哈希码不必是唯一的,但它应该分布良好.

class Person {
  final String firstName, lastName;

  Person(this.firstName, this.lastName);

  // Override hashCode using strategy from Effective Java,
  // Chapter 11.
  @override
  int get hashCode {
    int result = 17;
    result = 37 * result + firstName.hashCode;
    result = 37 * result + lastName.hashCode;
    return result;
  }

  // You should generally implement operator == if you
  // override hashCode.
  @override
  bool operator ==(dynamic other) {
    if (other is! Person) return false;
    Person person = other;
    return (person.firstName == firstName &&
        person.lastName == lastName);
  }
}

void main() {
  var p1 = Person('Bob', 'Smith');
  var p2 = Person('Bob', 'Smith');
  var p3 = 'not a person';
  assert(p1.hashCode == p2.hashCode);
  assert(p1 == p2);
  assert(p1 != p3);
}

Iteration

IterableIterator类支持for-in循环. 每当您创建一个可以提供for循环中使用的Iterator的类时,就扩展(如果可能)或实现Iterable. 实现Iterator定义实际的迭代能力.

class Process {
  // Represents a process...
}

class ProcessIterator implements Iterator<Process> {
  @override
  Process get current => ...
  @override
  bool moveNext() => ...
}

// A mythical class that lets you iterate through all
// processes. Extends a subclass of [Iterable].
class Processes extends IterableBase<Process> {
  @override
  final Iterator<Process> iterator = ProcessIterator();
}

void main() {
  // Iterable objects can be used with for-in.
  for (var process in Processes()) {
    // Do something with the process.
  }
}

Exceptions

Dart核心库定义了许多常见的异常和错误. 例外被认为是您可以提前计划并捕获的条件. 错误是您无法预期或计划的状况.

几个最常见的错误是:

NoSuchMethodError

当接收对象(可能为null)未实现方法时抛出.

ArgumentError

可以由遇到意外参数的方法引发.

引发特定于应用程序的异常是指示发生错误的常见方法. 您可以通过实现Exception接口来定义自定义异常:

class FooException implements Exception {
  final String msg;

  const FooException([this.msg]);

  @override
  String toString() => msg ?? 'FooException';
}

有关更多信息,请参见异常 (在语言导览中)和Exception API参考.

dart:async - asynchronous programming

异步编程通常使用回调函数,但Dart提供了替代方法: FutureStream对象. 未来就像对将来某个时间提供结果的承诺. 流是获取一系列值(例如事件)的方法. dart:async库( API参考 )中提供了Future,Stream等内容.

dart:async库可在Web应用程序和命令行应用程序中使用. 要使用它,请导入dart:async:

import 'dart:async';

Future

将来的对象经常出现在Dart库中,通常是由异步方法返回的对象. 将来完成时 ,就可以使用它的价值了.

Using await

在直接使用Future API之前,请考虑改为使用await . 使用await表达式的代码比使用Future API的代码更容易理解.

考虑以下功能. 它使用Future的then()方法连续执行三个异步函数,等待每个异步函数完成后再执行下一个异步函数.

runUsingFuture() {
  // ...
  findEntryPoint().then((entryPoint) {
    return runExecutable(entryPoint, args);
  }).then(flushThenExit);
}

具有await表达式的等效代码看起来更像同步代码:

runUsingAsyncAwait() async {
  // ...
  var entryPoint = await findEntryPoint();
  var exitCode = await runExecutable(entryPoint, args);
  await flushThenExit(exitCode);
}

async函数可以捕获来自Future的异常. 例如:

var entryPoint = await findEntryPoint();
try {
  var exitCode = await runExecutable(entryPoint, args);
  await flushThenExit(exitCode);
} catch (e) {
  // Handle the error...
}

有关使用await和相关Dart语言功能的更多信息,请参见异步编程代码实验室 .

Basic usage

您可以使用then()安排将来完成时运行的代码. 例如,由于HTTP请求可能需要一段时间,因此HttpRequest.getString()返回Future. 使用then()可以让您在Future完成并且承诺的字符串值可用时运行一些代码:

HttpRequest.getString(url).then((String result) {
  print(result);
});

使用catchError()处理Future对象可能引发的任何错误或异常.

HttpRequest.getString(url).then((String result) {
  print(result);
}).catchError((e) {
  // Handle or ignore the error.
});

then().catchError()模式是try - catch的异步版本.

Chaining multiple asynchronous methods

then()方法返回一个Future,它提供了一种有用的方式来以特定顺序运行多个异步函数. 如果在then()注册的回调返回Future, then()返回等效的Future. 如果回调返回任何其他类型的值, then()创建一个新的Future,并以该值作为补充.

Future result = costlyQuery(url);
result
    .then((value) => expensiveWork(value))
    .then((_) => lengthyComputation())
    .then((_) => print('Done!'))
    .catchError((exception) {
  /* Handle exception... */
});

在前面的示例中,这些方法按以下顺序运行:

  1. costlyQuery()
  2. expensiveWork()
  3. lengthyComputation()

这是使用await编写的相同代码:

try {
  final value = await costlyQuery(url);
  await expensiveWork(value);
  await lengthyComputation();
  print('Done!');
} catch (e) {
  /* Handle exception... */
}

Waiting for multiple futures

有时您的算法需要调用许多异步函数,并等待它们全部完成才能继续. 使用Future.wait()静态方法来管理多个Future并等待它们完成:

Future deleteLotsOfFiles() async =>  ...
Future copyLotsOfFiles() async =>  ...
Future checksumLotsOfOtherFiles() async =>  ...

await Future.wait([
  deleteLotsOfFiles(),
  copyLotsOfFiles(),
  checksumLotsOfOtherFiles(),
]);
print('Done with all the long steps!');

Stream

流对象出现在整个Dart API中,代表数据序列. 例如,使用流传递HTML事件(例如按钮单击). 您还可以将文件作为流读取.

Using an asynchronous for loop

有时,您可以使用异步for循环( await for )来代替使​​用Stream API.

考虑以下功能. 它使用Stream的listen()方法订阅文件列表,并传入搜索每个文件或目录的函数文字.

void main(List<String> arguments) {
  // ...
  FileSystemEntity.isDirectory(searchPath).then((isDir) {
    if (isDir) {
      final startingDir = Directory(searchPath);
      startingDir
          .list(
              recursive: argResults[recursive],
              followLinks: argResults[followLinks])
          .listen((entity) {
        if (entity is File) {
          searchFile(entity, searchTerms);
        }
      });
    } else {
      searchFile(File(searchPath), searchTerms);
    }
  });
}

具有await表达式的等效代码,包括异步for循环( await for ),看起来更像是同步代码:

Future main(List<String> arguments) async {
  // ...
  if (await FileSystemEntity.isDirectory(searchPath)) {
    final startingDir = Directory(searchPath);
    await for (var entity in startingDir.list(
        recursive: argResults[recursive],
        followLinks: argResults[followLinks])) {
      if (entity is File) {
        searchFile(entity, searchTerms);
      }
    }
  } else {
    searchFile(File(searchPath), searchTerms);
  }
}

有关使用await和相关Dart语言功能的更多信息,请参见异步编程代码实验室 .

Listening for stream data

要获取每个值的到达值,请使用listen()方法使用await for或订阅流:

// Find a button by ID and add an event handler.
querySelector('#submitInfo').onClick.listen((e) {
  // When the button is clicked, it runs this code.
  submitData();
});

在此示例中, onClick属性是由" submitInfo"按钮提供的Stream对象.

如果只关心一个事件,则可以使用诸如firstlastsingle的属性来获取它. 要在处理事件之前对其进行测试,请使用诸如firstWhere()lastWhere()singleWhere() .

如果您关心事件的子集,则可以使用诸如skip()skipWhile()take()takeWhile()where() .

Transforming stream data

通常,您需要先更改流数据的格式,然后才能使用它. 使用transform()方法生成具有不同数据类型的流:

var lines = inputStream
    .transform(utf8.decoder)
    .transform(LineSplitter());

本示例使用两个变压器. 首先,它使用utf8.decoder将整数流转换为字符串流. 然后,它使用LineSplitter将字符串流转换为单独的行流. 这些转换器来自dart:convert库(请参阅dart:convert部分 ).

Handling errors and completion

如何指定错误和完成处理代码取决于您使用异步for循环( await for )还是Stream API.

如果使用异步for循环,请使用try-catch处理错误. 在关闭流之后执行的代码将在异步for循环之后执行.

Future readFileAwaitFor() async {
  var config = File('config.txt');
  Stream<List<int>> inputStream = config.openRead();

  var lines = inputStream
      .transform(utf8.decoder)
      .transform(LineSplitter());
  try {
    await for (var line in lines) {
      print('Got ${line.length} characters from stream');
    }
    print('file is now closed');
  } catch (e) {
    print(e);
  }
}

如果使用Stream API,则通过注册onError侦听器来处理错误. 通过注册onDone侦听器在流关闭后运行代码.

var config = File('config.txt');
Stream<List<int>> inputStream = config.openRead();

inputStream
    .transform(utf8.decoder)
    .transform(LineSplitter())
    .listen((String line) {
  print('Got ${line.length} characters from stream');
}, onDone: () {
  print('file is now closed');
}, onError: (e) {
  print(e);
});

More information

有关在命令行应用程序中使用Future和Stream的一些示例,请参见dart:io浏览 . 另请参阅以下文章,代码实验室和教程:

dart:math - math and random

dart:math库( API参考 )提供了常用功能(例如正弦和余弦,最大值和最小值)以及常量(例如pie) . 数学库中的大多数功能都实现为顶级功能.

要在您的应用中使用此库,请导入dart:math.

import 'dart:math';

Trigonometry

数学库提供基本的三角函数:

// Cosine
assert(cos(pi) == -1.0);

// Sine
var degrees = 30;
var radians = degrees * (pi / 180);
// radians is now 0.52359.
var sinOf30degrees = sin(radians);
// sin 30° = 0.5
assert((sinOf30degrees - 0.5).abs() < 0.01);

Maximum and minimum

数学库提供max()min()方法:

assert(max(1, 1000) == 1000);
assert(min(1, -1000) == -1000);

Math constants

在数学库中找到您喜欢的常数pie等:

// See the Math library for additional constants.
print(e); // 2.718281828459045
print(pi); // 3.141592653589793
print(sqrt2); // 1.4142135623730951

Random numbers

使用Random类生成随机数. 您可以选择提供一个种子给Random构造函数.

var random = Random();
random.nextDouble(); // Between 0.0 and 1.0: [0, 1)
random.nextInt(10); // Between 0 and 9.

您甚至可以生成随机布尔值:

var random = Random();
random.nextBool(); // true or false

More information

有关方法的完整列表,请参考Math API参考 . 另请参阅num, intdouble的API参考.

dart:convert - decoding and encoding JSON, UTF-8, and more

dart:convert库( API参考 )具有用于JSON和UTF-8的转换器,并支持创建其他转换器. JSON是一种简单的文本格式,用于表示结构化对象和集合. UTF-8是一种常见的可变宽度编码,可以表示Unicode字符集中的每个字符.

dart:convert库可在Web应用程序和命令行应用程序中使用. 要使用它,请导入dart:convert.

import 'dart:convert';

Decoding and encoding JSON

使用jsonDecode()将JSON编码的字符串解码为Dart对象:

// NOTE: Be sure to use double quotes ("),
// not single quotes ('), inside the JSON string.
// This string is JSON, not Dart.
var jsonString = '''
  [
    {"score": 40},
    {"score": 80}
  ]
''';

var scores = jsonDecode(jsonString);
assert(scores is List);

var firstScore = scores[0];
assert(firstScore is Map);
assert(firstScore['score'] == 40);

使用jsonEncode()将受支持的Dart对象编码为JSON格式的字符串:

var scores = [
  {'score': 40},
  {'score': 80},
  {'score': 100, 'overtime': true, 'special_guest': null}
];

var jsonText = jsonEncode(scores);
assert(jsonText ==
    '[{"score":40},{"score":80},'
        '{"score":100,"overtime":true,'
        '"special_guest":null}]');

只有类型为int,double,String,bool,null,List或Map(带有字符串键)的对象才能直接编码为JSON. List和Map对象是递归编码的.

您有两个选项可以对无法直接编码的对象进行编码. 第一种是使用第二个参数调用encode() :一个函数,该函数返回可直接编码的对象. 您的第二个选择是忽略第二个参数,在这种情况下,编码器将调用对象的toJson()方法.

有关更多示例和指向JSON相关包的链接,请参见Using JSON .

Decoding and encoding UTF-8 characters

使用utf8.decode()将UTF8编码的字节解码为Dart字符串:

List<int> utf8Bytes = [
  0xc3, 0x8e, 0xc3, 0xb1, 0xc5, 0xa3, 0xc3, 0xa9,
  0x72, 0xc3, 0xb1, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3,
  0xae, 0xc3, 0xb6, 0xc3, 0xb1, 0xc3, 0xa5, 0xc4,
  0xbc, 0xc3, 0xae, 0xc5, 0xbe, 0xc3, 0xa5, 0xc5,
  0xa3, 0xc3, 0xae, 0xe1, 0xbb, 0x9d, 0xc3, 0xb1
];

var funnyWord = utf8.decode(utf8Bytes);

assert(funnyWord == 'Îñţérñåţîöñåļîžåţîờñ');

要将UTF-8字符流转换为Dart字符串, utf8.decoder对Stream transform()方法指定utf8.decoder

var lines =
    utf8.decoder.bind(inputStream).transform(LineSplitter());
try {
  await for (var line in lines) {
    print('Got ${line.length} characters from stream');
  }
  print('file is now closed');
} catch (e) {
  print(e);
}

使用utf8.encode()将Dart字符串编码为UTF8编码的字节列表:

List<int> encoded = utf8.encode('Îñţérñåţîöñåļîžåţîờñ');

assert(encoded.length == utf8Bytes.length);
for (int i = 0; i < encoded.length; i++) {
  assert(encoded[i] == utf8Bytes[i]);
}

Other functionality

dart:convert库还具有用于ASCII和utf-8(Latin1)的转换器. 有关详细信息,请参见dart:convert库API参考.

dart:html - browser-based apps

使用dart:html库对浏览器进行编程,操作DOM中的对象和元素,以及访问HTML5 API. DOM代表Document Object Model ,它描述HTML页面的层次结构.

dart:html的其他常见用法是操纵样式( CSS ),使用HTTP请求获取数据以及使用WebSockets交换数据. HTML5(和dart:html)具有许多本节不介绍的其他API. 仅网络应用程序可以使用dart:html,而命令行应用程序则不能.

要在您的网络应用中使用HTML库,请导入dart:html:

import 'dart:html';

Manipulating the DOM

要使用DOM,您需要了解Windows文档元素节点 .

Window对象代表Web浏览器的实际窗口. 每个窗口都有一个Document对象,该对象指向当前加载的文档. Window对象还具有各种API的访问器,例如IndexedDB(用于存储数据),requestAnimationFrame(用于动画)等. 在选项卡式浏览器中,每个选项卡都有其自己的Window对象.

使用Document对象,您可以在文档中创建和操作Element对象. 请注意,文档本身是一个元素,可以对其进行操作.

DOM为节点树建模. 这些节点通常是元素,但它们也可以是属性,文本,注释和其他DOM类型. 除了没有父节点的根节点之外,DOM中的每个节点都有一个父节点,并且可能有很多子节点.

Finding elements

要操作元素,首先需要一个表示它的对象. 您可以使用查询获取此对象.

使用顶级函数querySelector()querySelectorAll()查找一个或多个元素. 您可以按ID,类,标签,名称或它们的任意组合进行查询. CSS选择器规范指南定义了选择器的格式,例如使用#前缀指定类的ID和句点(.).

querySelector()函数返回与选择器匹配的第一个元素,而querySelectorAll()返回与选择器匹配的元素的集合.

// Find an element by id (an-id).
Element elem1 = querySelector('#an-id');

// Find an element by class (a-class).
Element elem2 = querySelector('.a-class');

// Find all elements by tag (<div>).
List<Element> elems1 = querySelectorAll('div');

// Find all text inputs.
List<Element> elems2 = querySelectorAll(
  'input[type="text"]',
);

// Find all elements with the CSS class 'class'
// inside of a <p> that is inside an element with
// the ID 'id'.
List<Element> elems3 = querySelectorAll('#id p.class');

Manipulating elements

您可以使用属性来更改元素的状态. Node及其子类型Element定义所有元素具有的属性. 例如,所有元素都具有可用于设置状态的classeshiddenidstyletitle属性. Element的子类定义其他属性,例如AnchorElementhref属性.

考虑以下在HTML中指定锚元素的示例:

<a id="example" href="/another/example">link text</a>

这个<a>标签指定一个具有href属性的元素和一个包含字符串" linktext"的文本节点(可通过text属性访问). 要更改链接所指向的URL,可以使用AnchorElement的href属性:

var anchor = querySelector('#example') as AnchorElement;
anchor.href = 'https://dart.dev';

通常,您需要在多个元素上设置属性. 例如,以下代码设置所有具有" mac"," win"或" linux"类的元素的hidden属性. 将hidden属性设置为true与将display:none添加到CSS具有相同的效果.

<!-- In HTML: -->
<p>
  <span class="linux">Words for Linux</span>
  <span class="macos">Words for Mac</span>
  <span class="windows">Words for Windows</span>
</p>
// In Dart:
final osList = ['macos', 'windows', 'linux'];
final userOs = determineUserOs();

// For each possible OS...
for (var os in osList) {
  // Matches user OS?
  bool shouldShow = (os == userOs);

  // Find all elements with class=os. For example, if
  // os == 'windows', call querySelectorAll('.windows')
  // to find all elements with the class "windows".
  // Note that '.$os' uses string interpolation.
  for (var elem in querySelectorAll('.$os')) {
    elem.hidden = !shouldShow; // Show or hide.
  }
}

当right属性不可用或不方便使用时,您可以使用Element的attributes属性. 此属性是Map<String, String> ,其中键是属性名称. 有关属性名称及其含义的列表,请参见" MDN属性"页面. 这是设置属性值的示例:

elem.attributes['someAttribute'] = 'someValue';

Creating elements

您可以通过创建新元素并将其附加到DOM来添加到现有HTML页面. 这是创建段落(<p>)元素的示例:

var elem = ParagraphElement();
elem.text = 'Creating is easy!';

您也可以通过解析HTML文本来创建元素. 任何子元素也将被解析和创建.

var elem2 = Element.html(
  '<p>Creating <em>is</em> easy!</p>',
);

请注意,在前面的示例中, elem2ParagraphElement .

通过为元素分配父项,将新创建的元素附加到文档. 您可以将元素添加到任何现有元素的子元素中. 在下面的示例中, body是一个元素,可以从children属性访问其子元素(作为List <Element>).

document.body.children.add(elem2);

Adding, replacing, and removing nodes

回想一下,元素只是一种节点. 您可以使用一个节点的所有子nodes的节点,它返回一个List <节点>(相对于财产children ,其省略了非元素节点). 获得此列表后,可以使用常规的List方法和运算符来操纵节点的子级.

要将节点添加为其父节点的最后一个子节点,请使用List add()方法:

querySelector('#inputs').nodes.add(elem);

To replace a node, use the Node replaceWith() method:

querySelector('#status').replaceWith(elem);

要删除节点,请使用Node remove()方法:

// Find a node by ID, and remove it from the DOM.
querySelector('#expendable').remove();

Manipulating CSS styles

CSS或级联样式表定义DOM元素的表示样式. 您可以通过在元素上附加ID和类属性来更改其外观.

每个元素都有一个classes字段,该字段是一个列表. 只需通过添加和删除此集合中的字符串来添加和删除CSS类. 例如,以下示例将warning类添加到元素:

var elem = querySelector('#message');
elem.classes.add('warning');

通过ID查找元素通常非常有效. 您可以使用id属性动态设置元素ID:

var message = DivElement();
message.id = 'message2';
message.text = 'Please subscribe to the Dart mailing list.';

您可以通过使用方法级联来减少此示例中的冗余文本:

var message = DivElement()
  ..id = 'message2'
  ..text = 'Please subscribe to the Dart mailing list.';

虽然最佳做法是使用ID和类将元素与一组样式相关联,但有时您希望将特定样式直接附加到该元素:

message.style
  ..fontWeight = 'bold'
  ..fontSize = '3em';

Handling events

要响应外部事件,例如单击,焦点更改和选择,请添加事件侦听器. 您可以将事件侦听器添加到页面上的任何元素. 事件分发和传播是一个复杂的主题. 如果您不熟悉Web编程,请研究细节 .

使用element .on Event .listen( function )添加事件处理程序,其中Event是事件名称, function是事件处理程序.

For example, here’s how you can handle clicks on a button:

// Find a button by ID and add an event handler.
querySelector('#submitInfo').onClick.listen((e) {
  // When the button is clicked, it runs this code.
  submitData();
});

事件可以通过DOM树上下传播. 要发现最初触发事件的元素,请使用e.target

document.body.onClick.listen((e) {
  final clickedElem = e.target;
  // ...
});

要查看可以为其注册事件侦听器的所有事件,请在API文档中查找Element及其子类的" onEventType"属性. 一些常见事件包括:

  • change
  • blur
  • keyDown
  • keyUp
  • mouseDown
  • mouseUp

Using HTTP resources with HttpRequest

HttpRequest类以前称为XMLHttpRequest,可让您从基于浏览器的应用程序中访问HTTP资源. 传统上,AJAX风格的应用程序大量使用HttpRequest. 使用HttpRequest从Web服务器动态加载JSON数据或任何其他资源. 您还可以动态地将数据发送到Web服务器.

Getting data from the server

HttpRequest静态方法getString()是从Web服务器获取数据的简便方法. 将awaitgetString()调用一起使用,以确保在继续执行之前拥有数据.

Future main() async {
  String pageHtml = await HttpRequest.getString(url);
  // Do something with pageHtml...
}

使用try-catch指定错误处理程序:

try {
  var data = await HttpRequest.getString(jsonUri);
  // Process data...
} catch (e) {
  // Handle exception...
}

如果您需要访问HttpRequest而不是访问它获取的文本数据,则可以使用request()静态方法代替getString() . 这是读取XML数据的示例:

Future main() async {
  HttpRequest req = await HttpRequest.request(
    url,
    method: 'HEAD',
  );
  if (req.status == 200) {
    // Successful URL access...
  }
  // ···
}

您还可以使用完整的API处理更有趣的情况. 例如,您可以设置任意标题.

The general flow for using the full API of HttpRequest is as follows:

  1. 创建HttpRequest对象.
  2. 使用GETPOST打开URL.
  3. 附加事件处理程序.
  4. 发送请求.

例如:

var request = HttpRequest();
request
  ..open('POST', url)
  ..onLoadEnd.listen((e) => requestComplete(request))
  ..send(encodedData);

Sending data to the server

HttpRequest可以使用HTTP方法POST将数据发送到服务器. 例如,您可能想动态地将数据提交到表单处理程序. 将JSON数据发送到RESTful Web服务是另一个常见的示例.

将数据提交到表单处理程序要求您提供名称/值对作为URI编码的字符串. (有关URI类的信息在Dart Library TourURIs部分. )如果要将数据发送到表单处理程序,还必须将Content-type标头设置为application/x-www-form-urlencode .

String encodeMap(Map<String, String> data) => data.keys
    .map((k) => '${Uri.encodeComponent(k)}=${Uri.encodeComponent(data[k])}')
    .join('&');

Future main() async {
  var data = {'dart': 'fun', 'angular': 'productive'};

  var request = HttpRequest();
  request
    ..open('POST', url)
    ..setRequestHeader(
      'Content-type',
      'application/x-www-form-urlencoded',
    )
    ..send(encodeMap(data));

  await request.onLoadEnd.first;

  if (request.status == 200) {
    // Successful URL access...
  }
  // ···
}

Sending and receiving real-time data with WebSockets

A WebSocket allows your web app to exchange data with a server interactively—no polling necessary. A server creates the WebSocket and listens for requests on a URL that starts with ws://—for example, ws://127.0.0.1:1337/ws. The data transmitted over a WebSocket can be a string or a blob. Often, the data is a JSON-formatted string.

要在您的Web应用程序中使用WebSocket,请首先创建一个WebSocket对象,并将WebSocket URL作为参数传递:

var ws = WebSocket('ws://echo.websocket.org');

Sending data

要在WebSocket上发送字符串数据,请使用send()方法:

ws.send('Hello from Dart!');

Receiving data

要在WebSocket上接收数据,请为消息事件注册一个侦听器:

ws.onMessage.listen((MessageEvent e) {
  print('Received message: ${e.data}');
});

消息事件处理程序接收MessageEvent对象. 该对象的data字段包含来自服务器的数据.

Handling WebSocket events

您的应用程序可以处理以下WebSocket事件:打开,关闭,错误和(如前所示)消息. 这是创建WebSocket对象并注册处理打开,关闭,错误和消息事件的处理程序的方法的示例:

void initWebSocket([int retrySeconds = 1]) {
  var reconnectScheduled = false;

  print("Connecting to websocket");

  void scheduleReconnect() {
    if (!reconnectScheduled) {
      Timer(Duration(seconds: retrySeconds),
          () => initWebSocket(retrySeconds * 2));
    }
    reconnectScheduled = true;
  }

  ws.onOpen.listen((e) {
    print('Connected');
    ws.send('Hello from Dart!');
  });

  ws.onClose.listen((e) {
    print('Websocket closed, retrying in ' + '$retrySeconds seconds');
    scheduleReconnect();
  });

  ws.onError.listen((e) {
    print("Error connecting to ws");
    scheduleReconnect();
  });

  ws.onMessage.listen((MessageEvent e) {
    print('Received message: ${e.data}');
  });
}

More information

本节几乎不涉及使用dart:html库的表面. 有关更多信息,请参见dart:html的文档. Dart具有用于更专业的Web API的其他库,例如Web音频, IndexedDBWebGL.

有关Dart网络库的更多信息,请参见网络库概述.

dart:io - I/O for servers and command-line apps

dart:io库提供用于处理文件,目录,进程,套接字,WebSocket和HTTP客户端和服务器的API.

通常,dart:io库实现并提升了异步API. 同步方法很容易阻塞应用程序,从而难以扩展. 因此,大多数操作都是通过Future或Stream对象返回结果的,Future或Stream对象是现代服务器平台(如Node.js)常见的模式.

dart:io库中的一些同步方法在方法名称上明显带有Sync后缀. 同步方法不在这里.

要使用dart:io库,您必须将其导入:

import 'dart:io';

Files and directories

The I/O library enables command-line apps to read and write files and browse directories. You have two choices for reading the contents of a file: all at once, or streaming. Reading a file all at once requires enough memory to store all the contents of the file. If the file is very large or you want to process it while reading it, you should use a Stream, as described in Streaming file contents.

Reading a file as text

读取使用UTF-8编码的文本文件时,可以使用readAsString()读取整个文件内容. 当各行很重要时,可以使用readAsLines() . 在这两种情况下,都将返回一个Future对象,该对象以一个或多个字符串的形式提供文件的内容.

Future main() async {
  var config = File('config.txt');
  var contents;

  // Put the whole file in a single string.
  contents = await config.readAsString();
  print('The file is ${contents.length} characters long.');

  // Put each line of the file into its own string.
  contents = await config.readAsLines();
  print('The file is ${contents.length} lines long.');
}

Reading a file as binary

以下代码将整个文件作为字节读取到int列表中. 对readAsBytes()的调用返回一个Future,它在可用时提供结果.

Future main() async {
  var config = File('config.txt');

  var contents = await config.readAsBytes();
  print('The file is ${contents.length} bytes long.');
}

Handling errors

要捕获错误以免导致未捕获的异常,可以在Future上注册catchError处理程序,或(在async函数中)使用try-catch:

Future main() async {
  var config = File('config.txt');
  try {
    var contents = await config.readAsString();
    print(contents);
  } catch (e) {
    print(e);
  }
}

Streaming file contents

使用流一次读取文件. 您可以使用Stream API或Dart 异步支持的一部分中的await for .

import 'dart:io';
import 'dart:convert';

Future main() async {
  var config = File('config.txt');
  Stream<List<int>> inputStream = config.openRead();

  var lines =
      utf8.decoder.bind(inputStream).transform(LineSplitter());
  try {
    await for (var line in lines) {
      print('Got ${line.length} characters from stream');
    }
    print('file is now closed');
  } catch (e) {
    print(e);
  }
}

Writing file contents

您可以使用IOSink将数据写入文件. 使用File openWrite()方法获取可以写入的IOSink. 默认模式FileMode.write完全覆盖文件中的现有数据.

var logFile = File('log.txt');
var sink = logFile.openWrite();
sink.write('FILE ACCESSED ${DateTime.now()}\n');
await sink.flush();
await sink.close();

要添加到文件的末尾,请使用可选的mode参数指定FileMode.append

var sink = logFile.openWrite(mode: FileMode.append);

要写入二进制数据,请使用add(List<int> data) .

Listing files in a directory

查找目录的所有文件和子目录是异步操作. list()方法返回一个Stream,当遇到文件或目录时该Stream发出一个对象.

Future main() async {
  var dir = Directory('tmp');

  try {
    var dirList = dir.list();
    await for (FileSystemEntity f in dirList) {
      if (f is File) {
        print('Found file ${f.path}');
      } else if (f is Directory) {
        print('Found dir ${f.path}');
      }
    }
  } catch (e) {
    print(e.toString());
  }
}

Other common functionality

File和Directory类包含其他功能,包括但不限于:

  • 创建文件或目录:文件和目录中的create()
  • 删除文件或目录:"文件和目录"中的delete()
  • 获取文件的长度:File中的length()
  • 随机访问文件:File中的open()

有关方法的完整列表,请参阅文件目录的API文档.

HTTP clients and servers

dart:io库提供了命令行应用程序可用于访问HTTP资源以及运行HTTP服务器的类.

HTTP server

HttpServer类提供用于构建Web服务器的低级功能. 您可以匹配请求处理程序,设置标头,流数据等.

以下示例Web服务器返回简单文本信息. 该服务器侦听端口8888和地址127.0.0.1(localhost),响应对路径/dart请求. 对于任何其他路径,响应为状态码404(找不到页面).

Future main() async {
  final requests = await HttpServer.bind('localhost', 8888);
  await for (var request in requests) {
    processRequest(request);
  }
}

void processRequest(HttpRequest request) {
  print('Got request for ${request.uri.path}');
  final response = request.response;
  if (request.uri.path == '/dart') {
    response
      ..headers.contentType = ContentType(
        'text',
        'plain',
      )
      ..write('Hello from the server');
  } else {
    response.statusCode = HttpStatus.notFound;
  }
  response.close();
}

HTTP client

HttpClient类可帮助您从Dart命令行或服务器端应用程序连接到HTTP资源. 您可以设置标头,使用HTTP方法以及读取和写入数据. HttpClient类在基于浏览器的应用程序中不起作用. 在浏览器中编程时,请使用dart:html HttpRequest类. 这是使用HttpClient的示例:

Future main() async {
  var url = Uri.parse('http://localhost:8888/dart');
  var httpClient = HttpClient();
  var request = await httpClient.getUrl(url);
  var response = await request.close();
  var data = await utf8.decoder.bind(response).toList();
  print('Response ${response.statusCode}: $data');
  httpClient.close();
}

More information

该页面显示了如何使用dart:io库的主要功能. 除了本节讨论的API外,dart:io库还提供了用于进程, 套接字Web套接字的 API . 有关服务器端和命令行应用程序开发的更多信息,请参见服务器端Dart概述.

有关其他dart:*库的信息,请参见库导览.

Summary

该页面向您介绍了Dart内置库中最常用的功能. 但是,它并未涵盖所有内置库. 您可能要研究的其他对象包括dart:collectiondart:typed_data,以及特定于平台的库,例如Dart Web开发库Flutter库.

您可以使用pub软件包管理器获得更多库. 集合库, 加密库, http 国际库和测试库只是可以使用pub安装的示例.

To learn more about the Dart language, see the language tour.

by  ICOPY.SITE