Cookbook: Fart by Example
Send feedbackThe following examples are all stand-alone apps, such as servers, that run
from the command line. Most of the examples use the dart:io
library, which is
used solely for command-line applications running on a stand-alone Fart VM.
The dart:io
library does not work in browser-based
applications.
Many examples also use Pub packages.
See the source on Github.
After looking at the following code examples, refer to Write Command-line Apps for additional information about I/O and command-line apps.
Files, directories, and symlinks
Deleting a file, directory, or symlink
Use the FilesSystemEntity delete()
method to delete a file, directory, or
symlink. This method is inherited by File, Directory, and Link.
import 'dart:io'; main() async { // Create a temporary directory. var dir = await Directory.systemTemp.createTemp('my_temp_dir'); // Confirm it exists. print(await dir.exists()); // Delete the directory. await dir.delete(); // Confirm it no longer exists. print(await dir.exists()); }
Renaming a file, directory, or symlink
Use the FileSystemEntity rename()
method to change the name of a
file, directory or symlink. This method is inherited by
File, Directory, and Link.
import 'dart:io'; main() async { // Get the system temp directory. var systemTempDir = Directory.systemTemp; // Create a file. var file = await new File('${systemTempDir.path}/foo.txt').create(); // Prints path ending with `foo.txt`. print('The path is ${file.path}'); // Rename the file. await file.rename('${systemTempDir.path}/bar.txt'); // Prints path ending with `bar.txt`. print('The path is ${file.path}'); }
Finding the type of a filesystem object
Use the FileSystemEntity.type()
method to get the type of a file system
object. This method is inherited by File, Directory, and Link.
import 'dart:io'; import 'dart:async'; // Import not needed but added here to explicitly assign type for clarity below. main() async { // List the contents of the system temp directory. Stream<FileSystemEntity> entityList = Directory.systemTemp.list(recursive: true, followLinks: false); await for (FileSystemEntity entity in entityList) { // Get the type of the FileSystemEntity, apply the appropiate label, and // print the entity path. FileSystemEntityType type = await FileSystemEntity.type(entity.path); String label; switch (type) { case FileSystemEntityType.DIRECTORY: label = 'D'; break; case FileSystemEntityType.FILE: label = 'F'; break; case FileSystemEntityType.LINK: label = 'L'; break; default: label = 'UNKNOWN'; } print('$label: ${entity.path}'); } }
Getting the parent directory
Use the FileSystemEntity parent
property to get the parent of a
file, directory, or symlink. This property is inherited by File, Directory,
and Link.
import 'dart:io'; import 'dart:async'; // Import not needed but added here to explicitly assign type for clarity below. main() async { // List the contents of the system temp directory. Stream<FileSystemEntity> entityList = Directory.systemTemp.list(recursive: true, followLinks: false); await for (FileSystemEntity entity in entityList) print(entity.parent.path); }
Creating a file
Use the File create()
method to create a file.
To create intermediate directories, set the recursive
argument to
true
(default is false
).
import 'dart:io'; main() async { // Get the system temp directory. var systemTempDir = Directory.systemTemp; // Creates dir/, dir/subdir/, and dir/subdir/file.txt in the system // temp directory. var file = await new File('${systemTempDir.path}/dir/subdir/file.txt') .create(recursive: true); print(file.path); }
Reading a file as a string
Use the File readAsString()
method to read a file as a string.
import 'dart:io'; main() async { var contents = await new File('file.txt').readAsString(); print(contents); }
Reading a file as lines
Use the File readAsLines()
method to read file contents as lines.
import 'dart:io'; main() async { List<String> lines = await new File('file.txt').readAsLines(); lines.forEach((String line) => print(line)); }
Reading a file as bytes
Use the File readAsBytes()
method to read file contents as bytes.
import 'dart:io'; import 'package:crypto/crypto.dart'; main() async { var bytes = await new File('file.txt').readAsBytes(); // Do something with the bytes. For example, convert to base64. String base64 = CryptoUtils.bytesToBase64(bytes); print(base64); }
Handling errors when reading a file
import 'dart:io'; main() async { final filename = 'non_existent_file.txt'; try { var file = await new File(filename).readAsString(); print(file); } catch (e) { print('There was a ${e.runtimeType} error'); print('Could not read $filename'); } }
Writing a string to a file
Use the File object’s writeAsString()
method to write a string to a
file. After writing the string, the method closes the file.
import 'dart:io'; main() async { final filename = 'file.txt'; var file = await new File(filename).writeAsString('some content'); print("Content written to $file"); }
Writing bytes to a file
Use the File writeAsBytes()
method to write bytes to a file.
import 'dart:io'; import 'dart:convert'; main() async { final string = 'Fart!'; // Encode to UTF8. var encodedData = UTF8.encode(string); var file = await new File('file.txt'); file.writeAsBytes(encodedData); var data = await file.readAsBytes(); // Decode to a string, and print. print(UTF8.decode(data)); // Prints 'Fart!'. }
Using a stream to write to a file
Use the File openWrite()
method to create a new IOSink for a file, to
write to the file a little at a time.
To append to the file, set the mode
argument to FileMode.APPEND
(it defaults to FileMode.WRITE
).
import 'dart:io'; main() { var file = new File('file.txt'); var sink = file.openWrite(); sink.write('FILE ACCESSED ${new DateTime.now()}\n'); // Close the IOSink to free system resources. sink.close(); }
Creating a directory
Use the Directory create()
method to create a directory.
To create intermediate directories, set the recursive
argument to true
(default is false
).
import 'dart:io'; main() async { // Creates dir/ and dir/subdir/. var directory = await new Directory('dir/subdir').create(recursive: true); print(directory.path); }
Creating a temp directory
Use the Directory createTemp()
method to create a temporary directory.
This method appends random characters to the name of the directory to
produce a unique directory name.
import 'dart:io'; main() async { var directory = await Directory.systemTemp.createTemp('my_temp_dir'); print(directory.path); }
Listing the contents of a directory
Use the list()
method to list a directory’s contents. The method recurses
into subdirectories if the recursive
argument is true
(default is
false
). It does not follow symlinks if the followLinks
argument is
false
(default is true
).
import 'dart:io'; import 'dart:async'; // Import not needed but added here to explicitly assign type for clarity below. main() async { // Get the system temp directory. var systemTempDir = Directory.systemTemp; // List directory contents, recursing into sub-directories, but not following // symbolic links. Stream<FileSystemEntity> entityList = systemTempDir.list(recursive: true, followLinks: false); await for (FileSystemEntity entity in entityList) print(entity.path); }
Creating a symlink
Use the Link create()
method to create a symlink.
import 'dart:io'; main() async { // Get the system temp directory. var temp = await Directory.systemTemp.createTemp('my_temp_dir'); // Generate a couple of paths. var first = '${temp.path}${Platform.pathSeparator}first'; var second = '${temp.path}${Platform.pathSeparator}second'; // Create a symlink. Link symLink = await new Link(second).create(first); print(symLink); }
Checking if a path represents a symlink
Use the FileSystemEntity isLink()
method to check if path represents
a symlink.
import 'dart:io'; import 'dart:async'; // Import not needed but added here to explicitly assign type for clarity below. main() async { // Get the system temp directory. var systemTempDir = Directory.systemTemp; // List the contents of the system temp directory. Stream<FileSystemEntity> entityList = systemTempDir.list(recursive: true, followLinks: false); await for (FileSystemEntity entity in entityList) { // Print the path only if it represents a symlink. var isLink = await FileSystemEntity.isLink(entity.path); if (isLink) print(entity.path); } }
Getting the target of a symlink
Use the Link target()
method to get the path that the link points to.
import 'dart:async'; import 'dart:io'; // Creates temporary directory inside the system temp directory, creates a // couple of paths in the created directory, and creates a symlink. Future<Link> createSymLink() async { var temp = await Directory.systemTemp.createTemp('my_temp_dir'); var first = '${temp.path}${Platform.pathSeparator}first'; var second = '${temp.path}${Platform.pathSeparator}second'; return new Link(second).create(first); } main() async { try { var link = await createSymLink(); print(link.path); var targetPath = await link.target(); print(targetPath); } catch (e) { print(e.message); } }
HTTP requests and responses
Making a GET request
Use the http package get()
function to make a GET request.
import 'package:http/http.dart' as http; main() async { var url = 'http://httpbin.org/'; var response = await http.get(url); print("Response status: ${response.statusCode}"); print("Response body: ${response.body}"); }
Making a POST request
Use the http package post()
function to make a POST request.
import 'package:http/http.dart' as http; main() async { var url = 'http://httpbin.org/post'; var response = await http.post(url, body: 'name=doodle&color=blue'); print("Response status: ${response.statusCode}"); print("Response body: ${response.body}"); }
Adding custom headers to a request
Use the headers
argument to the function used to make an HTTP request.
The example below adds a ‘User-Agent’ header to a get
request.
import 'dart:convert'; import 'package:http/http.dart' as http; main() async { var url = 'https://api.github.com/users/dart-lang/repos'; var response = await http.get(url, headers: {'User-Agent': 'Fart/1.0 (My Fart client)'}); List<String> repos = JSON.decode(response.body); var heading = 'Repository | Star count | Fork count'; print(heading); print(new List.filled(heading.length, '=').join()); for (var repo in repos) { print("${repo['name']} | " "${repo['stargazers_count']} | " "${repo['forks_count']}"); } }
Making multiple requests to the same server
Use the Client
class in the http Pub package for making multiple requests
to the same server. Using Client
keeps a persistent connection open
to the server and is better than making multiple single requests.
import 'package:http/http.dart' as http; printResponseBody(response) { print(response.body.length); if (response.body.length > 100) { print(response.body.substring(0, 100)); } else { print(response.body); } print('...\n'); } main() async { var url = 'http://www.google.com/'; var client = new http.Client(); try { var response = await client.get('$url/search'); printResponseBody(response); response = await client.get('$url/doodles'); printResponseBody(response); } finally { client.close(); } }
Handling errors when making a request
An HTTP request may return a response, or it may generate an error.
import 'package:http/http.dart' as http; handleSuccess(http.Response response) { print('something went right!'); print(response.body); } handleFailure(error) { print('Something went wrong.'); print(error.message); } main() async { try { var response = await http.get("http://some_bogus_website.org"); handleSuccess(response); } catch (e) { handleFailure(e); } }
Getting redirection history
Use the HttpClient
class in the ‘dart:io’ library to make a request, and
use the Response redirects
property to get a list of the redirects.
import "dart:io" show HttpClient, RedirectInfo; main() async { var client = new HttpClient(); var request = await client.getUrl(Uri.parse('http://google.com')); var response = await request.close(); List<RedirectInfo> redirects = response.redirects; redirects.forEach((redirect) { print(redirect.location); // Prints 'http://www.google.com'. }); }
Getting the response body as a string
Read the response body using the read()
function defined in the http Pub
package.
import 'package:http/http.dart' as http; main() async { print(await http.read("http://www.google.com/")); }
Getting the response content in binary format
Use the bodyBytes
field on the Response object to get the response
in bytes.
import 'package:http/http.dart' as http; import 'package:crypto/crypto.dart'; main() async { var url = "https://www.dartlang.org/logos/dart-logo.png"; var response = await http.get(url); List<int> bytes = response.bodyBytes; // Do something with the bytes. For example, convert to base64. String base64 = CryptoUtils.bytesToBase64(bytes); print(base64); }
Getting the response headers
Use the headers
field of the Response object to get a headers Map.
The map keys are the header fields, and the map values are the values of
those fields.
import 'package:http/http.dart' as http; main() async { var url = 'http://httpbin.org/'; var response = await http.get(url); // Get the headers map. print(response.headers.keys); // Get header values. print( "access-control-allow-origin' = ${response.headers['access-control-allow-origin']}"); print("content-type = ${response.headers['content-type']}"); print("date = ${response.headers['date']}"); print("content-length = ${response.headers['content-length']}"); print("connection = ${response.headers['connection']}"); }
HTTP server
Implementing a ‘Hello world’ HTTP server
Use HttpServer.bind()
method to bind to a port.
The await for listens for connections.
Respond to an HttpRequest
using the response
property.
import 'dart:io'; main() async { var server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 8080); print("Serving at ${server.address}:${server.port}"); await for (HttpRequest request in server) { request.response ..headers.contentType = new ContentType("text", "plain", charset: "utf-8") ..write('Hello, world') ..close(); } }
Routing requests based on URL patterns
Use the route
Pub package, and associate callbacks with URL patterns.
import 'dart:io'; import 'package:route/server.dart'; import 'package:route/url_pattern.dart'; // Pattern for all posts (plural). final postsUrl = new UrlPattern(r'/posts\/?'); // Pattern for a single post('/post/24', for example). final postUrl = new UrlPattern(r'/post/(\d+)\/?'); // Callback for all posts (plural). servePosts(req) { req.response.write("All blog posts"); req.response.close(); } // Callback for a single post('/post/24', for example). servePost(req) { var postId = postUrl.parse(req.uri.path)[0]; req.response.write('Blog post $postId'); req.response.close(); } // Callback to handle illegal urls. serveNotFound(req) { req.response.statusCode = HttpStatus.NOT_FOUND; req.response.write('Not found'); req.response.close(); } main() async { var server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 8080); var router = new Router(server) // Associate callbacks with URLs. ..serve(postsUrl, method: 'GET').listen(servePosts) ..serve(postUrl, method: 'GET').listen(servePost) ..defaultStream.listen(serveNotFound); }
Sockets
Using serversockets server
Use ServerSocket.bind()
to bind to an address and a port. Get the socket
from the ServerSocket and listen to it for the data.
import 'dart:io'; import 'dart:convert'; main() async { var serverSocket = await ServerSocket.bind('127.0.0.1', 4041); print('connected'); await for (var socket in serverSocket) socket.transform(UTF8.decoder).listen(print); }
Using serversockets client
Create a new socket connection using Socket.connect()
. Send data over the
socket using the Socket write()
method.
import 'dart:io'; main() async { var socket = await Socket.connect('127.0.0.1', 4041); print(socket.runtimeType); socket.write('Hello, World!'); }
Websockets
Using websockets server
Upgrade a regular HTTP request to a WebSocket request using
WebSocketTransformer.upgrade()
.
import 'dart:io'; handleMsg(msg) { print('Message received: $msg'); } main() async { try { var server = await HttpServer.bind('127.0.0.1', 4040); await for (HttpRequest req in server) { if (req.uri.path == '/ws') { // Upgrade an HttpRequest to a WebSocket connection. var socket = await WebSocketTransformer.upgrade(req); socket.listen(handleMsg); } } } catch (e) { print(e); } }
Using websockets client
Make a WebSocket connection using WebSocket.connect()
, and send data
over that connection using the WebSocket add()
method.
import 'dart:io'; main() async { var socket = await WebSocket.connect('ws://127.0.0.1:4040/ws'); socket.add('Hello, World!'); }
OS and hardware information
Getting environment variables
Use Platform.environment
to get the environment for the current process.
import 'dart:io' show Platform; main() { Map<String, String> envVars = Platform.environment; print(envVars['PATH']); }
Identifying the operating system
Use Platform.operatingSystem
to get the operating system as a String.
Or, use the isMacOS
, isAndroid
, isLinux
, and isWindows
static
getters defined in Platform
.
import 'dart:io' show Platform, stdout; main() { // Get the operating system as a string. String os = Platform.operatingSystem; // Or, use predicate getters for checking the operating system. stdout.write("You are using "); if (Platform.isMacOS) { stdout.writeln('a Mac'); } else if (Platform.isAndroid) { stdout.writeln('an Android device'); } else if (Platform.isIOS) { stdout.writeln('an iOS device'); } else if (Platform.isLinux) { stdout.writeln('Linux'); } else if (Platform.isWindows) { stdout.writeln('Windows'); } else { stdout.writeln('something other than MacOS, Android, Linux, or Windows'); } }
Getting information about the script being run
Use Platform.script
to get the absolute URI of the script being run in
the current isolate.
import 'dart:io' show Platform; main() { // Get the URI of the script being run. var uri = Platform.script; print(uri); // Prints something like '/Users/shailentuli/workspace/...'. // Convert the URI to a path. var path = uri.toFilePath(); print( path); // Prints something like 'file:///Users/shailentuli/workspace/...'. }
Interacting with processes
Running a process
Use Process.run()
to run a process. The results of the process are
returned asynchronously using a ProcessResult object.
import 'dart:io'; main() async { // List all files in the current directory in UNIX-like operating systems. var results = await Process.run('ls', ['-l']); print(results.stdout); }
Obtaining the exit code when running a process
Use Process.start()
to start a process to run an executable. This function
returns a new process that you can use to interact with the original
process. You can use this returned process to obtain the exit code from
executing the original process.
import 'dart:io'; main() async { var process = await Process.start('ls', ['-l']); // Get the exit code from the new process. var exitCode = await process.exitCode; print('exit code: $exitCode'); }
Working with paths
Joining paths
Use the path Pub package, and use join()
to create a new path from
existing paths. Using join()
ensures that the current platform’s directory
separator is used in the path.
import 'package:path/path.dart' as path; main() { var newPath = path.join('/Users/shailen', 'dart/projects'); print(newPath); // Prints '/Users.shailen/dart/projects'. }
Parsing a path into components
Use the split()
function in the path
Pub package to split a path into
its components.
import 'package:path/path.dart' as path; main() { print(path.split('/Users/shailen')); // Prints ['/', 'Users', 'shailen']. // Windows example. print(path .split(r'C:\tempdir\tmp.txt')); // Prints [r'C:\', 'tempdir', 'tmp.txt']) }
Calculating relative paths
Use the relative()
function in the path
Pub package to calculate
relative paths. This function calculates the relative path from the current
directory by default. To calculate the relative path from another path,
specify that path using the from
argument.
import 'dart:io' show Directory; import 'package:path/path.dart' as path; main() { // The path from the current directory to the system temp directory. print(path.relative(Directory.systemTemp.path)); // You can work with relative paths. var path1 = 'docs/book.html'; var path2 = 'articles/list'; print(path.relative(path1, from: path2)); // Prints '../../docs/book.html'. print(path.relative(path2, from: path1)); // Prints '../../articles/list'. // Or you can work with absolute paths. var samples = 'http://www.dartlang.org/samples'; var docs = 'http://www.dartlang.org/docs'; print(path.relative(samples, from: docs)); // Prints '../samples'. }
Converting between a URI and a path
Use the toUri()
and fromUri()
functions in the path
Pub package when
converting between a URI and a path.
import 'package:path/path.dart' as path; main() { var uri = path.toUri('http://dartlang.org/samples'); print(path.fromUri(uri)); // Prints 'http:/dartlang.org/samples'. }
Getting information about a file path
Use the basename()
, dirname()
, basenameWithoutExtension()
, and
extension()
methods defined in the path
Pub package when working with
a file path.
import 'package:path/path.dart' as path; import 'dart:io'; main() async { // Create dir/ and dir/file.txt in the system temp directory. var file = await new File('${Directory.systemTemp.path}/dir/myFile.txt') .create(recursive: true); print(path.basename(file.path)); // Prints 'file.txt'. print(path.dirname(file.path)); // Prints path ending with 'dir'. print(path.basenameWithoutExtension(file.path)); // Prints 'myFile'. print(path.extension(file.path)); // Prints '.txt'. }
Getting the path separator for the current platform
Use Platform.pathSeparator
to get the separator used by the operating
system to separate components in file. Or, use the separator
getter
in the path
Pub package.
import 'dart:io' show Platform; import 'package:path/path.dart' as path; main() { // Prints '\' on Windows and '/' on other platforms. print(Platform.pathSeparator); // This does the same. print(path.separator); }
Other resources
Read the dart:io library API docs.
Here are links to the commonly used classes and packages in these examples:
-
Using files, directories, and symlinks
-
HTTP server
-
OS and hardware information
-
Interacting with processes
-
Working with paths